What Automated Security Checks Do Claude Plugins Undergo? A Technical Deep Dive

Claude plugins undergo a multi-stage automated security pipeline including static invariant checks (I1-I9), schema validation, SSRF-protected external repo cloning, and AI-driven policy scanning before marketplace publication.

The anthropics/claude-plugins-community repository enforces rigorous automated security checks on every plugin submission through a defense-in-depth CI/CD pipeline. Before any plugin appears in the Claude Marketplace, it must pass two specialized GitHub Actions that validate static constraints, verify cryptographic pinning, and perform automated safety reviews against public policies.

The Two-Stage Security Pipeline

The repository implements automated security checks through two distinct GitHub Actions that execute sequentially on every pull request.

Stage 1: Static Validation with validate-plugins

The validate-plugins composite action serves as the first line of defense, executing nine critical static invariants (I1-I9) documented in .github/actions/validate-plugins/README.md. These invariants enforce marketplace-wide constraints including alphabetical sorting, duplicate name detection, description length limits, HTTPS-only URLs, and 40-character lowercase SHA pinning to prevent supply chain attacks.

For external plugins, the action clones repositories at the specific pinned SHA—verifying the SHA format conforms to I5's requirement for exactly 40-character hexadecimal strings—and runs claude plugin validate against the cloned manifest without executing untrusted code. The system implements an SSRF allow-list restricting network calls to github.com, gitlab.com, and bitbucket.org, and validates all contributor-controlled values (url, repo, sha, path) in .github/actions/validate-plugins/scripts/11-validate-invariants.sh before any shell interaction occurs.

The action also validates the full marketplace file against the canonical Zod schema from @anthropic-ai/claude-code, ensuring structural compliance before any policy scanning begins.

Stage 2: Policy Scanning with scan-plugins

The scan-plugins action performs a Claude-based safety review using the minimal policy prompt defined in .github/actions/scan-plugins/policy/prompt.md, referencing the public Software Directory Policy and Acceptable Use Policy. This AI-driven scan returns a pass/fail verdict and emits ::warning annotations (or ::error when fail-on-findings is enabled), summarizing results in a step-summary table.

Additionally, the static pin check in .github/actions/scan-plugins/lib/pin-check.sh flags floating package manager specifications like @latest or version ranges that could introduce unpinned code execution. The action runs with minimal permissions—restricted to contents: read and optional id-token: write—and limits network calls to allowed hosts for stronger isolation.

Defense-in-Depth Security Layers

The automated security checks operate across multiple defensive layers to ensure comprehensive vetting:

Layer What It Checks Implementation Location
Static Invariants I1-I9: alphabetical sorting, duplicates, HTTPS enforcement, SHA pinning, filename consistency, no shell metacharacters validate-plugins step 11 (.github/actions/validate-plugins/scripts/11-validate-invariants.sh)
Schema Validation Zod schema compliance via claude plugin validate validate-plugins step 20
External Validation Pinned SHA cloning, SSRF guards, re-validation of contributor inputs validate-plugins step 30
Policy Scan Claude safety review against public policies; floating specification detection scan-plugins steps 1-5
Isolation Read-only job permissions, restricted network hosts Both actions via permissions blocks

Running the Security Checks Locally and in CI

To mirror the CI validation pipeline locally, execute the validation scripts in sequence:

export ACTION_PATH=.github/actions/validate-plugins
export VALIDATE_TMP=/tmp/validate-plugins
export BASE_REF=origin/main
export MARKETPLACE_PATH=.claude-plugin/marketplace.json
export ALLOWED_HOSTS="github.com gitlab.com bitbucket.org"
mkdir -p "$VALIDATE_TMP"

bash $ACTION_PATH/scripts/00-detect-changes.sh
bash $ACTION_PATH/scripts/11-validate-invariants.sh   # static I1–I9 checks

bash $ACTION_PATH/scripts/20-validate-cli-marketplace.sh
bash $ACTION_PATH/scripts/30-validate-cli-external.sh # clone + validate external plugins

bash $ACTION_PATH/scripts/40-validate-cli-local.sh    # validate in-repo plugins

bash $ACTION_PATH/scripts/41-validate-aux-files.sh
bash $ACTION_PATH/scripts/90-report.sh

To integrate the policy scan into your GitHub workflow:

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

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

    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 }}
          # Uncomment to block on any finding:

          # fail-on-findings: "true"

Key Source Files and Their Roles

Summary

  • The anthropics/claude-plugins-community repository implements automated security checks through two GitHub Actions: validate-plugins and scan-plugins.
  • Static invariants (I1-I9) enforce marketplace constraints including HTTPS-only URLs, 40-character SHA pinning, and prohibition of shell metacharacters in contributor inputs.
  • External plugin validation clones repositories at cryptographically pinned SHAs with SSRF protection restricted to github.com, gitlab.com, and bitbucket.org.
  • AI policy scanning uses Claude to review submissions against public safety policies while the static pin check detects unpinned dependencies like @latest.
  • All checks run with minimal permissions and can be executed locally using the provided shell scripts or integrated into CI pipelines.

Frequently Asked Questions

What are the nine static invariants (I1-I9) checked during validation?

The invariants enforce alphabetical sorting of entries, duplicate name detection, description length limits, HTTPS-only URL requirements, SHA pinning verification (I5 specifically requires 40-character lowercase hex), filename-name consistency, prohibition of direct edits to marketplace.json, vendored path existence validation, and prevention of shell metacharacters in contributor-controlled values.

How does the system prevent SSRF attacks during external plugin validation?

The validate-plugins action restricts network calls to an SSRF allow-list containing only github.com, gitlab.com, and bitbucket.org. It validates all contributor-controlled values (url, repo, sha, path) before any shell interaction or network request occurs, ensuring no requests reach unauthorized internal or external endpoints.

What happens if a plugin fails the AI policy scan?

By default, the scan-plugins action emits ::warning annotations and allows the workflow to continue. When fail-on-findings is set to "true", the action emits ::error annotations and fails the CI check, preventing the plugin from reaching the marketplace until the safety issues are resolved.

Can developers run these automated security checks locally before submitting?

Yes. Developers can execute the same validation scripts used in CI by setting the required environment variables (ACTION_PATH, VALIDATE_TMP, BASE_REF, MARKETPLACE_PATH, ALLOWED_HOSTS) and running the numbered scripts in .github/actions/validate-plugins/scripts/ to perform I1-I9 invariant checks, schema validation, and external repo verification locally.

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 →