How Are Claude Plugins Security Scanned? Inside Anthropic's Two-Stage Pipeline

Claude plugins undergo mandatory automated security scanning through a two-stage pipeline that combines deterministic static analysis with LLM-based behavioral inspection, ensuring only vetted, reproducible code enters the community marketplace.

The anthropics/claude-plugins-community repository enforces enterprise-grade supply chain security through an automated validation system defined in the source. Every plugin submission is scrutinized by the Validate Plugins workflow, which orchestrates consecutive checks for version stability and runtime safety before any entry reaches .claude-plugin/marketplace.json.

Stage 1: Static Pin-Check for Supply Chain Integrity

The first stage operates deterministically without requiring Anthropic authentication. As implemented in .github/actions/scan-plugins/README.md (lines 18-26), the system inspects each plugin's .mcp.json configuration (and any plugin.json → mcpServers mappings) for floating package-manager specifications.

The classifier specifically detects patterns like npx …@latest or semantic version ranges that could resolve to different code at runtime. When the scanner identifies an unpinned launcher, it emits a ::warning annotation and records the specific finding under unpinned_autoexec_* output fields. This auth-free approach guarantees that supply chain risks are flagged even in forked repositories or external CI environments lacking API keys.

Stage 2: Claude Policy Scan for Behavioral Analysis

When Anthropic credentials are present—supplied via either a static ANTHROPIC_API_KEY or Workload Identity Federation—the pipeline advances to the intelligent review phase. The scan-plugins action launches the Claude CLI to perform deep behavioral analysis on the plugin source code.

The Policy Prompt and Read-Only Inspection

The action clones the plugin repository at the pinned SHA and invokes Claude with the minimal policy prompt stored in policy/prompt.md. According to .github/actions/scan-plugins/README.md (lines 70-81), the LLM is restricted to read-only file tools during analysis, ensuring the inspection environment cannot modify the codebase under review. This sandboxed approach allows Claude to audit for potentially malicious patterns without executing the code.

JSON Verdict and Enforcement

The policy scan returns a structured JSON verdict containing:

  • passes / violations: Boolean compliance indicators
  • may_make_external_network_calls: Flag indicating potential outbound network activity
  • may_download_additional_software: Flag signaling possible runtime installations

The scan-plugins action surfaces these results as ::warning or ::error annotations in the GitHub Actions log. As documented in the repository README (lines 9-10), only plugins that pass the combined scan are allowed to merge, creating a hard gate for marketplace entries.

GitHub Actions Implementation

The orchestration logic resides in .github/workflows/validate-plugins.yml (lines 31-55), which chains static tests, pin-check golden-vector tests, and the policy scan sequentially. The workflow triggers automatically on every pull request and push affecting marketplace files.

Core Components

The .github/actions/scan-plugins/ directory contains the implementation:

  • scripts/scan.sh: Core bash script handling repository cloning, Claude CLI invocation, and JSON verdict parsing
  • README.md: Technical documentation defining inputs like marketplace-path, anthropic-api-key, and fail-on-findings
  • policy/prompt.md: The minimal system prompt guiding Claude's security evaluation criteria

Example: Running the Security Scan Locally

Below is a minimal GitHub Actions workflow that mirrors the official validation job for testing individual plugin changes:

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

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write   # needed only if using WIF auth

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # 1️⃣ Static pin‑check (runs even without auth)

      - name: Run static pin‑check
        run: bash .github/actions/scan-plugins/test-pin-check.sh

      # 2️⃣ Claude policy scan (requires Anthropic auth)

      - name: Scan plugins with Claude
        uses: ./.github/actions/scan-plugins
        with:
          marketplace-path: .claude-plugin/marketplace.json
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}   # or use WIF

          fail‑on‑findings: "true"      # make the job fail on policy violations

Summary

  • Claude plugins are security scanned through a mandatory two-stage pipeline before merging into the marketplace.
  • Static pin-checks analyze .mcp.json for floating versions like npx @latest, storing findings in unpinned_autoexec_* fields without requiring API credentials.
  • Policy scans leverage the Claude CLI with the policy/prompt.md configuration to detect external network calls and unauthorized software downloads.
  • The Validate Plugins workflow orchestrates both stages automatically on every PR affecting marketplace configuration.
  • Only plugins returning a clean JSON verdict with passes: true are permitted to enter .claude-plugin/marketplace.json.

Frequently Asked Questions

What triggers the security scan for Claude plugins?

The Validate Plugins workflow initiates automatically on every pull request and push to files within the marketplace directory. This ensures continuous validation of the .claude-plugin/marketplace.json manifest and any referenced plugin configurations.

Can the static pin-check run without Anthropic API credentials?

Yes. The static analysis stage operates deterministically without authentication, scanning for unpinned executables and version ranges in .mcp.json and plugin.json files. Only the second stage requires an ANTHROPIC_API_KEY or Workload Identity Federation to launch the Claude CLI policy scan.

What specific behaviors does the Claude policy scan detect?

The policy scan specifically flags plugins that may_make_external_network_calls or may_download_additional_software during execution. The LLM returns a JSON verdict containing passes and violations indicators, which the scan-plugins action converts into GitHub Actions annotations for automated enforcement.

Where are scan results recorded when security checks fail?

Failures generate GitHub Actions annotations using ::warning or ::error syntax visible in workflow logs. The static check stores unpinned dependency findings in unpinned_autoexec_* output fields, while the policy scan surfaces behavioral violations in the structured JSON response parsed by .github/actions/scan-plugins/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 →