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

> Discover how Claude plugins are security scanned via Anthropic's two-stage pipeline. Learn about static analysis and LLM behavioral inspection for a safe marketplace.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: security-analysis
- Published: 2026-09-04

---

**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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/README.md) (lines 18-26), the system inspects each plugin's [`.mcp.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.mcp.json) configuration (and any [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/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`](https://github.com/anthropics/claude-plugins-community/blob/main/policy/prompt.md). According to [`.github/actions/scan-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/scan.sh)**: Core bash script handling repository cloning, Claude CLI invocation, and JSON verdict parsing
- **[`README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/README.md)**: Technical documentation defining inputs like `marketplace-path`, `anthropic-api-key`, and `fail-on-findings`
- **[`policy/prompt.md`](https://github.com/anthropics/claude-plugins-community/blob/main/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:

```yaml
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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.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`](https://github.com/anthropics/claude-plugins-community/blob/main/.mcp.json) and [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/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`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/scan-plugins/scripts/scan.sh).