Security Checks in the scan-plugins GitHub Action

The scan-plugins GitHub Action enforces a layered security review of external plugin entries through static pin-checks, URL validation, host allow-listing, command injection prevention, and AI-driven policy scanning using the Claude CLI.

The scan-plugins action is part of the anthropics/claude-plugins-community repository and validates marketplace entries before publication. It ensures that Claude plugins meet deterministic security standards by combining static analysis with dynamic AI policy enforcement.

Static Pin-Check Analysis

The action performs deterministic, auth-free validation of MCP server launchers to prevent the execution of unpinned code from remote registries.

Package Manager Launcher Classification

The static analysis logic resides in [lib/pin-check.sh](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/lib/pin-check.sh). It classifies each launcher into one of six categories:

  • pinned: Uses an immutable reference such as a specific version or SHA
  • floating: Uses a package manager runner (npx, bunx, uvx, pipx) with a mutable spec like @latest, version ranges, or bare package names
  • bare: Direct command without a package manager wrapper
  • vendored: Code included directly in the repository
  • local: References a local filesystem path
  • vcsref: Uses a version control reference

The check specifically flags floating specs that lack an explicit waiver. These launchers resolve code from a registry at session start, bypassing the entry's pinned SHA and introducing supply-chain risks.

To run this check manually for debugging:

source .github/actions/scan-plugins/lib/pin-check.sh
pin_check_tree "$PLUGIN_ROOT"

Input Validation and Allow-List Enforcement

Before cloning any repository, the action validates entry metadata in [scripts/scan.sh](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/scripts/scan.sh).

URL and SHA Verification

Lines 71-90 verify that every target entry supplies:

  • A non-empty url field
  • A 40-character SHA hash
  • URLs containing only safe characters
  • URLs matching the https:// scheme exclusively

Host Allow-List

Lines 82-86 restrict network fetches to a predefined allow-list:

  • github.com
  • gitlab.com
  • bitbucket.org

Any host outside this list triggers a warning and causes the scan to skip the entry entirely.

Unsafe Character and Path Detection

Lines 78-95 reject URLs or sub-directory paths containing characters that could lead to command injection or path traversal attacks. Lines 92-95 specifically ensure that source.path does not contain .. or other unsafe patterns before the action enters the cloned repository.

Repository Integrity Verification

Git Clone and Checkout Safety

Lines 97-104 of scripts/scan.sh perform a shallow clone of the declared URL, fetch the exact SHA, and check out the commit. If cloning, fetching, or checkout fails, the entry is skipped with a warning. This ensures the action only scans the exact code referenced by the pinned SHA, preventing time-of-check-to-time-of-use (TOCTOU) attacks.

AI-Driven Policy Scanning

Claude CLI Policy Execution

The action executes the Anthropic claude CLI in headless mode (lines 11-22 and 34-38 of scripts/scan.sh). It uses the minimal policy prompt defined in [policy/prompt.md](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/policy/prompt.md).

The CLI receives read-only file-tool permissions limited to Read, Glob, and Grep operations scoped strictly to the cloned directory. It returns a JSON verdict structured according to [policy/schema.json](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/policy/schema.json), containing:

  • passes: Boolean compliance status
  • summary: Human-readable description of findings
  • violations: List of specific policy breaches
  • Flags indicating unauthorized network calls or software installation attempts

Reporting and Failure Configuration

Verdict Parsing and Annotations

Lines 126-165 and 170-187 parse the JSON output and merge it with static pin-check results. The action emits GitHub workflow commands (::warning or ::error) and populates step-summary tables. It also sets action outputs including scanned, failed, and result for downstream consumption.

Configurable Fail-On-Findings

By default, findings generate non-blocking warnings. Setting fail-on-findings: true (documented in [README.md](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/README.md) at line 58) upgrades policy failures to ::error commands and aborts the job. For isolation, the action can run in a separate job with minimal permissions as noted in lines 44-51 of the README.

Implementation Example

Configure the action in your workflow to scan plugin directories on pull requests:


# .github/workflows/scan-plugins.yml

name: Scan Plugins
on:
  pull_request:
    paths: ['.claude-plugin/**']

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@<PINNED-SHA>
        with:
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          fail-on-findings: "true"

Summary

  • Static pin-checks in lib/pin-check.sh classify MCP launchers and block floating package manager specs that bypass SHA pinning
  • Input validation enforces HTTPS URLs, 40-character SHAs, and safe character sets while restricting hosts to GitHub, GitLab, and Bitbucket
  • Path safety prevents directory traversal by validating source.path before repository entry
  • Git integrity ensures exact commit checkout via shallow clones and precise SHA fetching
  • AI policy scanning uses the Claude CLI with read-only permissions to detect policy violations, network calls, and installation attempts
  • Configurable reporting allows choosing between warning annotations or hard failures via the fail-on-findings input

Frequently Asked Questions

What triggers a floating launcher warning in the pin-check?

A floating launcher warning occurs when the action detects MCP servers using package manager runners like npx, bunx, uvx, or pipx with mutable version specs such as @latest, semantic version ranges, or bare package names. These configurations resolve code from registries at runtime, bypassing the entry's pinned SHA and requiring an explicit waiver to pass validation according to the logic in lib/pin-check.sh.

How does the action prevent command injection attacks?

The action prevents command injection through multiple layers: it validates that URLs contain only safe characters (lines 78-95 of scripts/scan.sh), ensures sub-directory paths don't contain .. sequences (lines 92-95), restricts network requests to a predefined host allow-list (lines 82-86), and executes the Claude CLI with read-only file permissions scoped strictly to the cloned directory.

Can I run the security checks without failing the CI job?

Yes. By default, the fail-on-findings input is set to false, causing violations to emit ::warning annotations rather than ::error commands. Set fail-on-findings: "true" only when you want policy violations to block the workflow and prevent plugin publication, as documented in the action's README.

Which code hosting platforms are supported by the host allow-list?

The action restricts fetches to github.com, gitlab.com, and bitbucket.org. Any plugin entry referencing URLs outside these hosts triggers a warning and is skipped during the scan, as implemented in lines 82-86 of scripts/scan.sh.

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 →