How the Security Review Pipeline for Claude Plugins Works: A Technical Deep Dive
The security review pipeline for Claude plugins is a multi-stage CI process that combines deterministic schema validation, nine static security invariants, and AI-powered policy analysis to vet every plugin before it reaches the public marketplace.
The anthropics/claude-plugins-community repository maintains a rigorous automated validation system for its plugin ecosystem. This security review pipeline for Claude plugins validates structural integrity and enforces safety requirements through deterministic GitHub Actions, ensuring that only compliant, secure extensions are published to the marketplace.
The Three-Stage Architecture
The pipeline is implemented as two complementary composite actions that execute sequentially on every pull request touching the .claude-plugin/ directory tree.
Stage 1: Schema and Invariant Validation
The validate-plugins composite action enforces structural correctness through canonical schema checks and static security invariants. Located in .github/actions/validate-plugins/, this action runs the claude plugin validate CLI command against the marketplace manifest and enforces rules I1 through I9.
These invariants govern naming conventions, alphabetical sorting, SHA-pinning requirements, URL safety, and shell metacharacter prohibition. The validation logic resides in .github/actions/validate-plugins/scripts/11-validate-invariants.sh for rule enforcement and .github/actions/validate-plugins/scripts/20-validate-cli-marketplace.sh for schema validation.
For external plugins, the action clones repositories at their exact pinned source.sha into an isolated temporary directory and validates the plugin.json file without executing any code from the cloned repository.
Stage 2: Policy and Safety Scanning
The scan-plugins composite action performs a Claude-based policy review against Anthropic’s Software Directory Policy and Acceptable Use Policy. This action, defined in .github/actions/scan-plugins/, launches a headless claude -p invocation using the minimal prompt defined in .github/actions/scan-plugins/policy/prompt.md.
The scan evaluates the entire plugin payload, including declared surfaces and hidden files, and generates a JSON verdict containing boolean fields such as passes, may_make_external_network_calls, and may_download_additional_software.
Before the LLM review, the action runs a static pin check via .github/actions/scan-plugins/lib/pin-check.sh to flag unpinned "auto-exec" servers. This script detects floating package-manager invocations like npx, pipx, bunx, or uvx that use @latest, version ranges, or omit version specifiers entirely.
Stage 3: Reporting and Enforcement
Both actions emit results as GitHub annotations using ::warning and ::error workflow commands. The validate-plugins action generates its final markdown report via .github/actions/validate-plugins/scripts/90-report.sh, while scan-plugins produces a step-summary table.
Each action outputs structured JSON files indicating scanned and failed states. The pipeline supports optional job failure through the fail-on-findings input parameter, which can be set to "true" to block merges when violations are detected.
Pipeline Execution Flow
PR Validation Workflow
The .github/workflows/validate-plugins.yml workflow triggers on pull requests modifying .claude-plugin/** paths. It detects changed entries, runs invariant checks I1-I9, validates the marketplace JSON, clones external plugins at their pinned SHAs, and checks auxiliary configuration files including .mcp.json, .lsp.json, and hooks/hooks.json.
# .github/workflows/validate-plugins.yml
name: Validate Plugins
on:
pull_request:
paths:
- '.claude-plugin/**'
jobs:
validate:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@<PINNED-SHA>
with:
marketplace-path: .claude-plugin/marketplace.json
Security Scan Workflow
Running in parallel or sequentially, .github/workflows/scan-plugins.yml executes the policy scan. It performs static pin checks, invokes the Claude LLM with the policy prompt, and surfaces violations through GitHub’s annotation system.
# .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"
Nightly Drift Detection
A scheduled workflow, validate-plugins-nightly.yml, runs validate-plugins with validate-all-external: true to detect deletions or force-pushes that break previously pinned SHAs in the .claude-plugin/marketplace.json manifest.
Core Security Guarantees
The security review pipeline for Claude plugins enforces several critical protections:
- No arbitrary code execution: External plugins are cloned into temporary directories where only the static
claude plugin validatecommand runs. No scripts from cloned repositories are executed during validation. - SSRF protection: The system maintains a whitelist of allowed hosts (
github.com,gitlab.com,bitbucket.org) and rejects bare IP addresses through theallowed-hostsinput parameter. - Dependency pinning: The static pin check in
lib/pin-check.shprevents submission of plugins that invoke package managers without explicit version pins. - Credential cross-service detection: The LLM policy prompt explicitly instructs Claude to flag code that reads credentials belonging to one service and transmits them to a different service.
- Structural integrity: Invariants I1-I9 ensure the marketplace data is well-formed, alphabetically sorted, duplicate-free, and that all external sources reference 40-character SHA commits.
Summary
- The security review pipeline for Claude plugins operates as a deterministic, isolated CI process using GitHub Actions.
- Stage 1 validates schema compliance and enforces nine static security invariants through the
validate-pluginsaction. - Stage 2 performs AI-powered policy analysis via the
scan-pluginsaction, including static pin checks for unpinned executors. - Stage 3 surfaces violations as GitHub annotations and markdown reports, with optional
fail-on-findingsenforcement. - The pipeline prevents code execution from external repositories by cloning only to validate
plugin.jsonstatic files. - Nightly drift detection ensures pinned SHAs remain valid against upstream repository changes.
Frequently Asked Questions
What happens if a plugin fails the security review pipeline?
Failed validations surface as GitHub annotations and workflow logs. If fail-on-findings is set to "true" in the workflow configuration, the CI job fails and blocks the pull request from merging. The 90-report.sh script generates a detailed markdown report outlining specific invariant violations or policy breaches.
How does the pipeline prevent code execution from external repositories?
The validate-plugins action clones external repositories into isolated temporary directories and runs only the claude plugin validate command against the static plugin.json file. According to the security model documented in .github/actions/validate-plugins/README.md, no scripts, binaries, or install hooks from the cloned repository are executed during the validation process.
What are the I1-I9 invariants checked during validation?
The nine invariants enforce marketplace data quality and security basics, including alphabetical sorting of entries, uniqueness constraints, valid semantic versioning, 40-character SHA pinning for external sources, URL safety verification, and prohibition of shell metacharacters in plugin names. These rules are implemented in .github/actions/validate-plugins/scripts/11-validate-invariants.sh.
How does the policy scan detect potential security risks?
The scan-plugins action uses a constrained LLM prompt at .github/actions/scan-plugins/policy/prompt.md to evaluate whether plugin code violates Anthropic’s Software Directory Policy or Acceptable Use Policy. It specifically checks for unauthorized external network calls, additional software downloads, and credential cross-service leakage, returning a structured JSON verdict that the CI pipeline interprets for pass/fail decisions.
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 →