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

> Discover the robust automated security checks Claude plugins face, from invariant checks and schema validation to AI policy scanning, ensuring a safe marketplace experience.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: deep-dive
- Published: 2026-08-24

---

**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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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:

```bash
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:

```yaml
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

- **[`.github/actions/validate-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/README.md)** - Documents static invariants I1-I9 and the overall validation flow
- **[`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh)** - Implements the I1-I9 checks programmatically
- **[`.github/actions/scan-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/README.md)** - Describes the Claude-based policy scan and static pin check functionality
- **[`.github/actions/scan-plugins/policy/prompt.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/policy/prompt.md)** - The minimal policy prompt fed to Claude for safety review verdicts
- **[`.github/actions/scan-plugins/lib/pin-check.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/lib/pin-check.sh)** - Performs static analysis to flag floating package manager specifications

## 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`](https://github.com/anthropics/claude-plugins-community/blob/main/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.