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 indicatorsmay_make_external_network_calls: Flag indicating potential outbound network activitymay_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 parsingREADME.md: Technical documentation defining inputs likemarketplace-path,anthropic-api-key, andfail-on-findingspolicy/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.jsonfor floating versions likenpx @latest, storing findings inunpinned_autoexec_*fields without requiring API credentials. - Policy scans leverage the Claude CLI with the
policy/prompt.mdconfiguration to detect external network calls and unauthorized software downloads. - The
Validate Pluginsworkflow orchestrates both stages automatically on every PR affecting marketplace configuration. - Only plugins returning a clean JSON verdict with
passes: trueare 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →