# How the Claude Plugin Marketplace Validation and Security Scanning Process Works

> Discover how the Claude plugin marketplace ensures safety and compliance. Learn about its automated CI pipeline, schema validation, and security scanning stages for secure plugin integration.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: how-to-guide
- Published: 2026-08-25

---

**The Claude plugin marketplace employs a fully automated CI pipeline via the `validate-plugins` composite GitHub Action that enforces strict schema compliance and security invariants through seven distinct validation stages, including change detection, invariant hardening, canonical schema validation, and isolated external plugin verification.**

The `anthropics/claude-plugins-community` repository maintains a robust validation framework to ensure every plugin entry meets security and structural standards before publication. This **Claude plugin marketplace validation** system operates as a composite GitHub Action that orchestrates multiple shell scripts to detect changes, enforce invariants, and validate both local and external plugin manifests against the official Claude SDK schema.

## The Seven-Stage Validation Pipeline

The validation process executes sequentially through specialized shell scripts located in `.github/actions/validate-plugins/scripts/`. Each stage performs distinct checks to guarantee marketplace integrity.

### 1. Change Detection with [`00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/00-detect-changes.sh)

The pipeline begins by identifying which plugins were added, removed, or modified in the pull request. The [`00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/00-detect-changes.sh) script builds a scoped list of changed entries, ensuring that historic defects in unchanged plugins do not block new contributions. This scoped list drives the `scope-errors-to-changed` functionality, which downgrades violations in untouched entries from errors to warnings.

### 2. Invariant Hardening via [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh)

The [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh) script enforces eleven custom rules (I1–I11) on the full [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) file. These invariants prevent common security and structural issues:

- **I1–I2**: Enforce global alphabetical ordering and uniqueness of plugin names.
- **I3–I5**: Validate description length constraints, enforce HTTPS-only URLs, and require a 40-character SHA-256 pin for every external source (with an optional exemption list).
- **I6–I7**: In per-file repositories, verify that each file name matches the internal `.name` field and prevent direct editing of the assembled [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json).
- **I8**: Confirm that vendored source paths contain a [`.claude-plugin/plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/plugin.json) file.
- **I9**: Scan all string fields under `source` for shell-metacharacters to prevent command injection attacks.
- **I10**: Disallow hidden Unicode characters (zero-width spaces, bidirectional overrides, BOM) in names and descriptions.
- **I11**: Validate that plugin names match the regex `^[a-z0-9][a-z0-9-]{1,63}$`.

Violations report as **errors** or **warnings**, with the latter optionally promoted to failures via the `fail-on-warnings` input parameter.

### 3. Canonical Schema Validation

The action installs the latest `@anthropic-ai/claude-code` package and executes `claude plugin validate <marketplace.json>` against the current JSON. This step validates the marketplace against the **up-to-date Zod schema** defined in the official Claude SDK, eliminating schema drift by removing the need for vendored JSON schemas within the repository.

### 4. External Plugin Security Scanning

For plugins referencing external repositories, the [`30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/30-validate-cli-external.sh) script implements a hardened verification process:

- **Host Allowlisting**: Validates URLs against an allowlist containing `github.com`, `gitlab.com`, and `bitbucket.org` to block SSRF attacks.
- **Immutable Checkout**: Clones the external repository into an isolated temporary directory and checks out the exact pinned SHA-256 commit.
- **Static Validation Only**: Executes `claude plugin validate` against the external [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) without executing any code from the cloned repository.
- **Synthetic Manifest Generation**: For entries marked `strict:false` that lack a [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json), the pipeline generates a minimal synthetic manifest using `jq` and validates it.

This design ensures that malicious external repositories cannot execute arbitrary code during the CI process.

### 5. Local Plugin Validation

The [`40-validate-cli-local.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/40-validate-cli-local.sh) script validates all in-repository plugin folders touched by the PR using the same `claude plugin validate` command, ensuring local modifications meet identical standards to external entries.

### 6. Auxiliary Files Parsing

The [`41-validate-aux-files.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/41-validate-aux-files.sh) script parses supplementary configuration files—including [`.mcp.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.mcp.json), [`.lsp.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.lsp.json), and [`hooks/hooks.json`](https://github.com/anthropics/claude-plugins-community/blob/main/hooks/hooks.json)—to confirm they are well-formed JSON. Malformed auxiliary files trigger immediate workflow failures to prevent runtime crashes.

### 7. Reporting and Status Determination

Finally, [`90-report.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/90-report.sh) generates a comprehensive markdown report summarizing errors, warnings, changed entries, external plugins, and validated folders. The script sets the job output `result` to `pass` or `fail` based on the accumulated validation state.

## Security Guarantees and Attack Mitigations

The validation pipeline implements multiple defensive layers to protect against supply chain attacks and injection vulnerabilities.

### Immutable SHA Pinning Requirements

External plugins must reference an immutable 40-character SHA-256 commit hash. The workflow rejects any entry lacking a valid SHA unless explicitly exempted, ensuring that plugin code cannot change unexpectedly after listing approval.

### SSRF Protection Through Host Allowlisting

The system validates all external URLs against a strict hostname allowlist. Any URL pointing to an IP address or unapproved domain aborts the clone operation, preventing Server-Side Request Forgery attacks.

### Shell Injection Defenses

The [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh) script scans source fields for dangerous characters using an `has_unsafe_chars` helper. All values interpolated into shell commands are double-quoted and protected by `--` end-of-options flags, eliminating command injection vectors.

### Temporary Directory Isolation

Cloned external repositories exist only within temporary directories that are deleted immediately after validation. This guarantees no persistent side-effects or cache poisoning between workflow runs.

## Running the Validator Locally

Developers can execute the validation pipeline locally to debug issues before submitting pull requests:

```bash

# Configure environment variables

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

mkdir -p "$VALIDATE_TMP"

# Execute validation scripts sequentially

bash $ACTION_PATH/scripts/00-detect-changes.sh
bash $ACTION_PATH/scripts/11-validate-invariants.sh
bash $ACTION_PATH/scripts/20-validate-cli-marketplace.sh
bash $ACTION_PATH/scripts/30-validate-cli-external.sh
bash $ACTION_PATH/scripts/40-validate-cli-local.sh
bash $ACTION_PATH/scripts/41-validate-aux-files.sh
bash $ACTION_PATH/scripts/90-report.sh

```

For CI integration, reference the composite action in your workflow:

```yaml
name: Validate Plugins
on:
  pull_request:
    paths:
      - '.claude-plugin/**'
      - '*/.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

```

## Key Implementation Files

| Component | Path | Purpose |
|-----------|------|---------|
| Composite Action definition | [`.github/actions/validate-plugins/action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/action.yml) | Orchestrates the validation steps |
| Design documentation | [`.github/actions/validate-plugins/README.md`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/README.md) | Describes validation layers and security model |
| Change detection | [`.github/actions/validate-plugins/scripts/00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/00-detect-changes.sh) | Identifies modified plugins in PRs |
| Invariant checks | [`.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 I1–I11 hardening rules |
| External validation | [`.github/actions/validate-plugins/scripts/30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/30-validate-cli-external.sh) | Clones and validates external repos at pinned SHAs |
| Report generation | [`.github/actions/validate-plugins/scripts/90-report.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/90-report.sh) | Generates markdown summary and sets job outputs |

## Summary

- The **Claude plugin marketplace validation** process runs as a composite GitHub Action executing seven specialized shell scripts in sequence.
- **Invariant hardening** (I1–I11) enforces structural rules including SHA-256 pinning, Unicode sanitization, and shell-injection prevention.
- **Canonical schema validation** uses the live `@anthropic-ai/claude-code` package to verify against the latest Zod schema without vendored drift.
- **External plugin validation** operates under strict security constraints: host allowlisting, immutable SHA checkout, and static-only analysis with no code execution.
- The `scope-errors-to-changed` feature prevents legacy defects from blocking clean pull requests by downgrading historical violations to warnings.

## Frequently Asked Questions

### What happens if a plugin violates the invariant rules?

Violations report as **errors** or **warnings** depending on severity. When `scope-errors-to-changed` is enabled, violations in untouched legacy entries downgrade to warnings, while new or modified plugins must pass all checks. Setting `fail-on-warnings: true` promotes all warnings to hard failures.

### How does the system prevent malicious code from external repositories?

The validation pipeline **never executes code** from external repositories. It only performs static manifest validation using `claude plugin validate`. External repos clone into isolated temporary directories using strictly pinned SHAs, and hostnames are allowlisted to `github.com`, `gitlab.com`, and `bitbucket.org` to prevent SSRF attacks.

### Can I run the validation locally before submitting a PR?

Yes. Export the required environment variables (`ACTION_PATH`, `VALIDATE_TMP`, `BASE_REF`, `MARKETPLACE_PATH`) and execute the shell scripts in `.github/actions/validate-plugins/scripts/` sequentially, starting with [`00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/00-detect-changes.sh) and ending with [`90-report.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/90-report.sh).

### What is the difference between strict and non-strict external plugins?

Entries marked `strict:true` must provide a valid [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) manifest in their repository. Entries with `strict:false` that lack a manifest file receive a **synthetic manifest** generated via `jq` containing minimal metadata, which is then validated against the schema. Both types require a pinned SHA-256 commit hash.