What Are Unpinned Auto‑exec Runtimes in Claude Plugins?

Unpinned auto‑exec runtimes are MCP servers declared in a Claude plugin manifest that execute code from floating package specifications—such as @latest or version ranges—allowing runtime code to change without a new plugin version.

Every Claude plugin in the anthropics/claude-plugins-community repository declares external executable services through .mcp.json or plugin.json files. When these services use unpinned auto‑exec runtimes, the code that runs at session start is resolved dynamically from package registries, creating a potential security gap between the plugin's pinned source code and its actual runtime behavior.

How Unpinned Auto‑exec Runtimes Are Detected

The scan-plugins GitHub Action identifies these conditions through a dedicated classifier script.

The Pin‑Check Classifier

In lib/pin-check.sh (lines 8‑14), the deterministic launcher‑pin classifier scans MCP server declarations for package‑manager runners invoked with floating specifications:


# From .github/actions/scan-plugins/lib/pin-check.sh

# Detects: npx, bunx, uvx, pipx with @latest, ^, >=, or bare names

The script flags launchers like npx my-tool@latest, bunx my-tool@^1.2, or uvx my-tool where the package specification is not locked to an exact version.

Detection Outputs

When the scan completes, it adds two fields to the JSON output as documented in the action's README (lines 28‑33):

Field Type Meaning
unpinned_autoexec_runtime boolean Whether any floating spec was detected
unpinned_autoexec_specs array List of offending package specifications

These values appear in the step summary table and in the scanned/pin-scanned action outputs.

What Triggers an Unpinned Auto‑exec Runtime

A runtime becomes "unpinned" when the launcher command uses any of these floating specifications:

  • Dist‑tags: my-tool@latest
  • Version ranges: my-tool@^1.2.0, my-tool@>=2.0.0
  • Bare names: my-tool (implicitly latest)

Conversely, an exact version like my-tool@1.2.3 is considered pinned and does not trigger the warning.

Example: Floating Spec (Unpinned)

{
  "myServer": {
    "command": "npx",
    "args": ["my-tool@latest"]
  }
}

Scan result:

{
  "name": "my-plugin",
  "unpinned_autoexec_runtime": true,
  "unpinned_autoexec_specs": ["my-tool@latest"]
}

Example: Exact Version (Pinned)

{
  "myServer": {
    "command": "npx",
    "args": ["my-tool@1.2.3"]
  }
}

Scan result:

{
  "name": "my-plugin",
  "unpinned_autoexec_runtime": false,
  "unpinned_autoexec_specs": []
}

Security Implications of Unpinned Auto‑exec Runtimes

The core risk stems from a version mismatch: the plugin's marketplace entry pins the source code to a specific source.sha, but a floating package specification can fetch different code each time the plugin launches. According to the anthropics/claude-plugins-community source code, this creates a supply‑chain exposure where untrusted code could be introduced at runtime without any change to the plugin itself.

The detection specifically targets auto‑executing code—MCP servers declared in the plugin manifest that run automatically at session start. Package invocations inside skills/, commands/, or agents/ markdown files are out of scope because they are agent‑invoked and permission‑gated, as noted in the scan‑plugins README (lines 39‑42).

Controlling Unpinned Auto‑exec Runtime Detection

Default Behavior: Warning Only

By default, the scan-plugins action reports unpinned auto‑exec runtimes as warnings without failing the workflow.

Enforcing Hard Failures

Set the workflow input fail-on-unpinned-autoexec: true to convert any detection into a hard failure:

- uses: ./.github/actions/scan-plugins
  with:
    fail-on-unpinned-autoexec: true

Waiving Specific Packages

Repository maintainers can suppress detections per‑package using a local waiver file named launch-shape-waivers. Each line follows the format:


<plugin-name> <package-prefix>/

For example, with this waiver:


my-plugin my-tool/

The floating spec my-tool@latest will be considered waived, and unpinned_autoexec_runtime will report false.

Key Source Files

File Role
.github/actions/scan-plugins/lib/pin-check.sh Core classifier identifying floating specs
.github/actions/scan-plugins/README.md Detection documentation and output schema
.github/actions/scan-plugins/policy/schema.json JSON schema defining unpinned_autoexec_* properties
Plugin manifests (.mcp.json, plugin.json) Declarations scanned for floating specifications

Summary

  • Unpinned auto‑exec runtimes occur when Claude plugin MCP servers use floating package specifications that resolve to different code at runtime.
  • The scan-plugins action detects these via lib/pin-check.sh, outputting unpinned_autoexec_runtime and unpinned_autoexec_specs fields.
  • Floating specs include @latest, semver ranges (^, >=), and bare package names; exact versions are pinned and safe.
  • By default, detection produces warnings; enable fail-on-unpinned-autoexec: true for enforcement.
  • Use launch-shape-waivers to exclude specific packages from detection when necessary.

Frequently Asked Questions

What package managers trigger unpinned auto‑exec runtime detection?

The pin-check.sh classifier monitors npx, bunx, uvx, and pipx launchers. Any of these invoked with a floating specification will flag the runtime as unpinned.

Why are skills and commands excluded from this check?

Package invocations inside skills/, commands/, or agents/ markdown are agent‑invoked and permission‑gated, meaning they require explicit user action rather than auto‑executing at session start. Only manifest‑declared MCP servers run automatically.

Can I use @latest in my plugin without failing the scan?

Yes, by adding a waiver to your repository's launch-shape-waivers file. Format the entry as plugin-name package-prefix/ to suppress detection for that specific package while keeping other enforcement active.

Does pinned source code protect against unpinned auto‑exec runtimes?

No. The source.sha in a plugin's marketplace entry pins the plugin's own code, not its external dependencies. A floating spec in .mcp.json can still fetch different runtime code on each launch, creating a reproducibility and security gap.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →