# What Are the Validation Layers in the validate-plugins Action?

> Explore validation layers in the validate-plugins action. Ensure Claude plugins meet upstream standards and security requirements through schema, security, and quality checks.

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

---

**The `validate-plugins` composite action enforces three distinct validation layers—canonical schema compliance, security and policy invariants, and per-plugin quality checks—to ensure every Claude plugin meets upstream standards and organizational security requirements.**

The `anthropics/claude-plugins-community` repository maintains a rigorous validation pipeline for community-contributed Claude plugins. Understanding the **validation layers in the validate-plugins action** is essential for contributors and DevOps teams who need to ensure their plugins pass automated checks before merging. Each layer is implemented as a numbered shell script in the `.github/actions/validate-plugins/scripts/` directory, forming a comprehensive defense-in-depth strategy.

## Layer 1: Security and Policy Invariants (Step 11)

The first layer to execute applies static organization-wide hardening rules that act as a policy floor independent of upstream requirements. Implemented in [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh), this layer enforces **invariants I1 through I9**, which include:

- **Alphabetical ordering** of marketplace entries
- **Description length** constraints
- **URL format** validation for repository sources
- **SHA format** verification for pinned commits
- **Vendored path existence** checks
- **Shell metacharacter** detection and rejection

These rules are not derived from the upstream `@anthropic-ai/claude-code` schema; rather, they represent organizational security boundaries. The script utilizes helper functions from [`lib/common.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/lib/common.sh), including `assert_safe_path` and `assert_safe_url`, to sanitize inputs before they reach downstream validation stages.

## Layer 2: Canonical Schema Validation (Step 20)

After security invariants pass, the action validates structural compliance against the official Claude plugin schema. Step 20, defined in [`scripts/20-validate-cli-marketplace.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/20-validate-cli-marketplace.sh), executes the `claude plugin validate` CLI command against the marketplace manifest (typically [`.claude-plugin/marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/marketplace.json)) or individual [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) files.

This layer guarantees full compliance with the upstream **Zod definition** maintained by Anthropic. It catches schema mismatches such as missing required fields, incorrect data types, or invalid enum values that would cause runtime failures in Claude Code. Unlike the policy layer, this validation is strictly upstream-driven and changes automatically when the canonical schema evolves.

## Layer 3: Per-Plugin Quality Checks (Steps 30, 40, and 41)

The final validation layer operates on individual plugin artifacts rather than the aggregate marketplace, splitting into three distinct execution paths:

### External Plugin Validation (Step 30)

For plugins referencing external repositories, [`scripts/30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/30-validate-cli-external.sh) clones each changed plugin at its pinned SHA and runs CLI validation. When `strict:false` is configured, the script synthesizes a minimal manifest to accommodate legacy or experimental plugin structures without failing the pipeline.

### Local Plugin Validation (Step 40)

For in-repo plugins, [`scripts/40-validate-cli-local.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/40-validate-cli-local.sh) iterates over every changed plugin folder within the repository and executes the same `claude plugin validate` checks applied to external plugins, ensuring consistency between community contributions and first-party extensions.

### Auxiliary File Validation (Step 41)

The final step parses runtime configuration files using [`scripts/41-validate-aux-files.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/41-validate-aux-files.sh). It validates **auxiliary files** such as [`.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 ensure they are well-formed JSON and contain valid configuration structures required for plugin execution.

## Implementing the validate-plugins Action in Your Workflow

To integrate these three validation layers into your CI pipeline, reference the composite action in your workflow configuration:

```yaml

# .github/workflows/validate-plugins.yml

name: Validate Plugins
on:
  pull_request:
    paths:
      - '.claude-plugin/**'
      - 'plugins/**'
      - '*/.claude-plugin/**'
      - '*/agents/**'
      - '*/skills/**'
      - '*/commands/**'

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

```

## Running Validation Locally

You can execute the identical validation pipeline locally by setting the required environment variables and running the shell scripts sequentially:

```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      # Detect changed entries/folders

bash $ACTION_PATH/scripts/11-validate-invariants.sh # Layer 1 – policy invariants

bash $ACTION_PATH/scripts/20-validate-cli-marketplace.sh # Layer 2 – canonical schema

bash $ACTION_PATH/scripts/30-validate-cli-external.sh   # Layer 3 – external plugins

bash $ACTION_PATH/scripts/40-validate-cli-local.sh      # Layer 3 – local plugins

bash $ACTION_PATH/scripts/41-validate-aux-files.sh     # Layer 3 – aux files

bash $ACTION_PATH/scripts/90-report.sh                # Summarise results

```

## Summary

- **Security Layer (Step 11):** Enforces organizational policy invariants (I1-I9) including path safety, URL validation, and formatting rules via [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh).
- **Canonical Layer (Step 20):** Validates upstream schema compliance using the Claude CLI against [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) via [`20-validate-cli-marketplace.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/20-validate-cli-marketplace.sh).
- **Quality Layer (Steps 30-41):** Performs granular validation on external plugins, local plugins, and auxiliary configuration files to ensure runtime readiness.

## Frequently Asked Questions

### What is the execution order of the validation layers?

The pipeline executes in the following sequence: **Step 11** (Security Invariants) runs first to filter out policy violations, followed by **Step 20** (Canonical Schema), then **Step 30** (External Plugins), **Step 40** (Local Plugins), and finally **Step 41** (Auxiliary Files). This order ensures that structural schema violations are caught only after security risks are eliminated.

### How does the security layer differ from the canonical schema layer?

The **security layer** enforces organization-specific hardening rules (such as forbidding shell metacharacters and enforcing alphabetical ordering) that are not part of the upstream Claude plugin specification. The **canonical schema layer** strictly validates against the official Anthropic Zod schema and will fail if the plugin structure deviates from the `claude plugin validate` requirements.

### Can I run the validate-plugins action locally without GitHub Actions?

Yes. By exporting the environment variables expected by the scripts—`ACTION_PATH`, `VALIDATE_TMP`, `BASE_REF`, `MARKETPLACE_PATH`, and `ALLOWED_HOSTS`—you can execute the shell scripts directly in any POSIX-compliant environment. This mirrors the GitHub Actions behavior exactly, including the three-layer validation sequence.

### What are the I1-I9 invariants checked in the security layer?

The invariants cover **alphabetical ordering** of entries, **description length** limits, **URL format** validation for repository sources, **SHA format** verification, **vendored path existence** confirmation, and **prohibition of shell metacharacters** in sensitive fields. These nine rules form a static policy floor defined in [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh) using helper functions from [`lib/common.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/lib/common.sh).