AI-PLUGIN-SCANNER(1)

NAME

ai-plugin-scannerSecurity and best-practices scanner for AI Plugins, covering Codex, Claude, Opencode, Gemini & more. Scores trust for…

SYNOPSIS

$pipx install plugin-scanner

INFO

97 stars
2 forks
0 views

DESCRIPTION

Security and best-practices scanner for AI Plugins, covering Codex, Claude, Opencode, Gemini & more. Scores trust for plugins 0-100.

README

HOL Guard

HOL Guard Version Plugin Scanner Version HOL Guard Downloads Plugin Scanner Downloads Python 3.10+ CI Publish Container Image OpenSSF Scorecard License GitHub Stars Lint: ruff

Hashgraph Online LogoProtect your harness locally with hol-guard. Use plugin-scanner when you need maintainer and CI checks for plugins, skills, MCP servers, and marketplace packages.

PyPI Package (hol-guard)
PyPI Package (plugin-scanner)
HOL Plugin Registry
HOL GitHub Organization
Report an Issue

Start Here

If you want to...InstallStart with
protect Codex, Claude Code, Cursor, Gemini, or OpenCode before tools runhol-guardhol-guard start
lint and verify packages in CI before releaseplugin-scannerplugin-scanner verify .

Guard Quickstart

pipx run hol-guard bootstrap
pipx run hol-guard run codex --dry-run
pipx run hol-guard run codex
pipx run hol-guard approvals
pipx run hol-guard receipts

What you get from Guard:

  • Detects local harness config on your machine
  • Records a baseline before you trust a tool
  • Pauses cleanly on new or changed artifacts before launch
  • Queues blocked changes in a localhost approval center when the harness cannot prompt inline
  • Stores receipts locally so you can review decisions later
  • Keeps sync optional until you actually want shared history

See docs/guard/get-started.md for the full local flow.

Guard commands at a glance
  • hol-guard start Shows the next step for the harnesses Guard found.
  • hol-guard bootstrap Detects the best local harness, starts the approval center, and installs Guard in front of it.
  • hol-guard status Shows what Guard is watching now.
  • hol-guard install <harness> Creates the launcher shim for that harness.
  • hol-guard run <harness> --dry-run Records the current state once before you trust it.
  • hol-guard run <harness> Reviews changes before launch and hands blocked sessions to the approval center when needed.
  • hol-guard approvals Lists pending approvals or resolves them from the terminal.
  • hol-guard receipts Shows local approval and block history.
Harness approval strategy
  • claude-code Guard prefers Claude hooks first, then the local approval center when the shell cannot prompt.
  • codex Guard owns artifact approval today through the local approval center. App Server is the future path for richer in-client approvals.
  • cursor Guard respects Cursor’s native tool approval and focuses on artifact trust before launch.
  • opencode Guard authors package-level policy while OpenCode keeps native allow or deny rules.
  • gemini Guard scans extensions and falls back to the local approval center for blocked changes.

Scanner Quickstart

pipx install plugin-scanner
plugin-scanner lint .
plugin-scanner verify .
# GitHub Actions PR gate
- name: AI plugin quality gate
  uses: hashgraph-online/ai-plugin-scanner-action@v1
  with:
    plugin_dir: "."
    fail_on_severity: high
    min_score: 80

When to add plugin-scanner:

  • You publish plugins, skills, or marketplace packages
  • You want a CI gate before release
  • You need SARIF, verification payloads, or submission artifacts

If your repository uses a Codex marketplace root like .agents/plugins/marketplace.json, keep plugin_dir: ".". The scanner will discover local ./plugins/... entries automatically, scan each local plugin manifest, and skip remote marketplace entries instead of treating the repo root as a single plugin.

Need More Detail?

Scanner reference: trust scoring, installs, ecosystems, and CLI commands

How Trust Scoring Works

The scanner now emits explicit trust provenance alongside the quality grade:

  • bundled skills use the published HCS-28 baseline adapter ids, weights, and denominator rules directly
  • MCP configuration trust uses the same HCS-style adapter, weight, and contribution-mode pattern locally
  • top-level Codex plugin trust uses the same HCS-style adapter, weight, and contribution-mode pattern locally

Current local specs:

This keeps the quality grade and the trust score separate. Signals like SECURITY.md remain visible, but their weight is now a named adapter weight rather than an inferred side effect of raw category points.

Quick Start For Contributors

git clone https://github.com/hashgraph-online/ai-plugin-scanner.git
cd ai-plugin-scanner
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest -q

Install The Package You Need

Guard package:

pip install hol-guard

Scanner package:

pip install plugin-scanner

Cisco-backed scanner analysis is optional:

pip install "plugin-scanner[cisco]"

The cisco extra installs the published cisco-ai-skill-scanner package from PyPI so the scanner remains publishable on PyPI and the optional Cisco analysis path works with standard package metadata.

If you want both tools in one shell during local development:

pipx install hol-guard
pipx install plugin-scanner

Container-first environments can use the published image instead:

docker run --rm \
  -v "$PWD:/workspace" \
  ghcr.io/hashgraph-online/ai-plugin-scanner:<version> \
  scan /workspace --format text

Command names by package:

hol-guard start
plugin-scanner verify .

Ecosystem Support

EcosystemDetection Surfaces
Codex.codex-plugin/plugin.json, marketplace.json, .agents/plugins/marketplace.json
Claude Code.claude-plugin/plugin.json, .claude-plugin/marketplace.json
Gemini CLIgemini-extension.json, commands/**/*.toml
OpenCodeopencode.json, opencode.jsonc, .opencode/commands, .opencode/plugins

Use --ecosystem auto (default) to scan all detected packages in a repository, or select a single ecosystem explicitly.

What The Scanner Checks

plugin-scanner supports a full quality suite:

  • scan for full-surface security and release analysis
  • lint for rule-oriented authoring feedback
  • verify for runtime and install-surface readiness checks
  • submit for artifact-backed submission gating
  • doctor for targeted diagnostics and troubleshooting bundles

The scanner evaluates only the surfaces a plugin actually exposes, then normalizes the final score across applicable checks. A plugin is not rewarded or penalized for optional surfaces it does not ship.

CategoryMax PointsCoverage
Manifest Validation31plugin.json, required fields, semver, kebab-case, recommended metadata, interface metadata, interface links and assets, safe declared paths
Security24SECURITY.md, LICENSE, hardcoded secret detection, dangerous MCP commands, MCP transport hardening, risky approval defaults
Operational Security20SHA-pinned GitHub Actions, write-all, privileged untrusted checkout patterns, Dependabot, dependency lockfiles
Best Practices15README.md, skills directory, SKILL.md frontmatter, committed .env, .codexignore
Marketplace15.agents/plugins/marketplace.json validity, legacy marketplace.json compatibility, policy fields, safe source paths
Skill Security15Cisco integration status, elevated skill findings, analyzability
Code Quality10eval, new Function, shell-injection patterns

CLI Usage

# Scan a plugin directory
plugin-scanner ./my-plugin

Auto-detect all supported ecosystems inside a repo (default)

plugin-scanner ./plugins-repo --ecosystem auto

Scan only Claude package surfaces

plugin-scanner ./plugins-repo --ecosystem claude

List supported ecosystems

plugin-scanner --list-ecosystems

Output JSON

plugin-scanner ./my-plugin --json

Write a SARIF report for GitHub code scanning

plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif

Fail CI on findings at or above high severity

plugin-scanner ./my-plugin --fail-on-severity high

Require Cisco skill scanning with a strict policy

plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict

Quality Suite Commands

# Summary scan (legacy form still works)
plugin-scanner scan ./my-plugin --format json --profile public-marketplace

Scan a multi-plugin repo from the marketplace root

plugin-scanner scan . --format json

Rule-oriented lint (with optional mechanical fixes)

plugin-scanner lint ./my-plugin --list-rules plugin-scanner lint ./my-plugin --explain README_MISSING plugin-scanner lint ./my-plugin --fix --profile strict-security

Runtime readiness verification

plugin-scanner verify ./my-plugin --format json plugin-scanner verify . --format json plugin-scanner verify ./my-plugin --online --format text

Artifact-backed submission gate

plugin-scanner submit ./my-plugin --profile public-marketplace --attest dist/plugin-quality.json

Diagnostic bundle

plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip

Advanced reference: specs, action publishing, automation, and examples

Codex Spec Alignment

The scanner follows the current Codex plugin packaging conventions more closely:

  • local manifest paths should use ./ prefixes
  • .agents/plugins/marketplace.json is the preferred marketplace manifest location
  • root marketplace.json is still supported in compatibility mode
  • interface metadata no longer requires an undocumented type field
  • verify performs an MCP initialize handshake before probing declared capabilities

lint --fix preserves or adds the documented ./ prefixes instead of stripping them away.

For repo-scoped marketplaces, scan, lint, verify, and doctor can target the repository root directly. submit remains intentionally single-plugin so the emitted artifact points at one concrete plugin package.

Config + Baseline Example

# .plugin-scanner.toml
[scanner]
profile = "public-marketplace"
baseline_file = "baseline.txt"
ignore_paths = ["tests/*", "fixtures/*"]

[rules] disabled = ["README_MISSING"] severity_overrides = { CODEXIGNORE_MISSING = "low" }

Example Output

🔗 Plugin Scanner v2.0.0
Scanning: ./my-plugin

── Manifest Validation (31/31) ── ✅ plugin.json exists +4 ✅ Valid JSON +4 ✅ Required fields present +5 ✅ Version follows semver +3 ✅ Name is kebab-case +2 ✅ Recommended metadata present +4 ✅ Interface metadata complete if declared +3 ✅ Interface links and assets valid if declared +3 ✅ Declared paths are safe +3

── Security (16/16) ── ✅ SECURITY.md found +3 ✅ LICENSE found +3 ✅ No hardcoded secrets +7 ✅ No dangerous MCP commands +0 ✅ MCP remote transports are hardened +0 ✅ No approval bypass defaults +3

── Operational Security (0/0) ── ✅ Third-party GitHub Actions pinned to SHAs +0 ✅ No write-all GitHub Actions permissions +0 ✅ No privileged untrusted checkout patterns +0 ✅ Dependabot configured for automation surfaces +0 ✅ Dependency manifests have lockfiles +0

── Skill Security (15/15) ── ✅ Cisco skill scan completed +3 ✅ No elevated Cisco skill findings +8 ✅ Skills analyzable +4

Findings: critical:0, high:0, medium:0, low:0, info:0

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Final Score: 100/100 (A - Excellent) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Report Formats

FormatUse Case
textHuman-readable terminal summary with category totals and findings
jsonStructured integrations and findings for tooling and dashboards
markdownPull request, issue, or review-ready summaries
sarifGitHub code scanning uploads and security automation

Scanner Signals

The scanner currently detects or validates:

  • Hardcoded secrets such as AWS keys, GitHub tokens, OpenAI keys, Slack tokens, GitLab tokens, and generic password or token patterns
  • Dangerous MCP command patterns such as rm -rf, sudo, curl|sh, wget|sh, eval, exec, and PowerShell or cmd /c shells
  • Insecure MCP remotes, including non-HTTPS endpoints and non-loopback HTTP transports
  • Risky Codex defaults such as approval bypass and unrestricted sandbox defaults inside shipped plugin config or docs
  • Publishability issues in interface metadata, HTTPS links, and declared asset paths
  • Workflow hardening gaps including unpinned third-party actions, write-all, privileged checkout patterns, missing Dependabot, and missing lockfiles
  • Skill-level issues surfaced by Cisco skill-scanner when the optional integration is installed

CI And Automation

Add the scanner to a plugin repository CI job:

permissions:
  contents: read
  security-events: write

jobs: scan-plugin: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: hashgraph-online/ai-plugin-scanner-action@v1 with: plugin_dir: "." mode: scan profile: public-marketplace min_score: 80 fail_on_severity: high format: sarif upload_sarif: true

For a multi-plugin repo, the same workflow can stay pointed at plugin_dir: "." as long as the repository has .agents/plugins/marketplace.json with local ./plugins/... entries.

Local pre-commit style hook:

repos:
  - repo: local
    hooks:
      - id: plugin-scanner
        name: Plugin Scanner
        entry: plugin-scanner
        language: system
        types: [directory]
        pass_filenames: false
        args: ["./"]

GitHub Action

The scanner ships with a composite GitHub Action source bundle in action/action.yml.

GitHub Marketplace has two important constraints for actions:

  • the published action must live in a dedicated public repository with a single root action.yml
  • that repository cannot contain workflow files

Because the scanner repository itself contains CI and release workflows, the Marketplace listing should be published from a separate action-only repository.

The dedicated action-repository guide now lives directly in action/README.md.

Automated Action Publication

The source repository can publish the GitHub Action automatically into a dedicated public action repository.

Configure:

  • repository secret ACTION_REPO_TOKEN It should be a token that can create or update repositories and releases in the canonical and compatibility action repositories.
  • optional repository variable ACTION_CANONICAL_REPOSITORY Defaults to hashgraph-online/ai-plugin-scanner-action.
  • optional repository variable ACTION_COMPAT_REPOSITORY Defaults to hashgraph-online/hol-codex-plugin-scanner-action.

When changes land on main, publish-action-repo.yml will:

  • create the canonical Marketplace repository if it does not already exist
  • sync the root-ready action.yml, repo-specific README.md, LICENSE, and SECURITY.md into both the canonical repo and the legacy compatibility repo
  • push the immutable release tag such as v2.0.0
  • move the floating v1 tag
  • create or update the corresponding release in each action repository

GitHub Marketplace still requires the one-time listing publication step in the dedicated action repository UI, but after that this repository can keep the action repository current automatically.

Plugin Author Submission Flow

The action can also handle submission intake. A plugin repository can wire the scanner into CI so a passing scan opens or reuses a submission issue in awesome-codex-plugins.

It also emits automation-friendly machine outputs:

  • score, grade, grade_label, max_severity, and findings_total as GitHub Action outputs
  • a concise markdown summary in the job summary by default
  • an optional machine-readable registry payload file for downstream registry, badge, or awesome-list automation

The intended path is:

  1. Add the scanner action to plugin CI.
  2. Require min_score: 80 and a severity gate such as fail_on_severity: high.
  3. Enable submission mode with a token that has issues:write on hashgraph-online/awesome-codex-plugins.
  4. When the plugin clears the threshold, the action opens or reuses a submission issue.
  5. The issue body includes machine-readable registry payload data, so registry automation can ingest the same submission event.

Example:

permissions:
  contents: read

jobs: scan-plugin: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6

  - name: Scan and submit if eligible
    id: scan
    uses: hashgraph-online/ai-plugin-scanner-action@v1
    with:
      plugin_dir: &quot;.&quot;
      min_score: 80
      fail_on_severity: high
      submission_enabled: true
      submission_score_threshold: 80
      submission_token: ${{ secrets.AWESOME_CODEX_PLUGINS_TOKEN }}

  - name: Print submission issue
    if: steps.scan.outputs.submission_performed == &#39;true&#39;
    run: echo &quot;${{ steps.scan.outputs.submission_issue_urls }}&quot;

submission_token is required when submission_enabled: true. This flow is idempotent. If the plugin repository was already submitted, the action reuses the existing open issue instead of opening duplicates by matching an exact hidden plugin URL marker in the existing issue body.

Registry Payload For Plugin Ecosystem Automation

If you want to feed the same scan into a registry, badge pipeline, or another plugin ecosystem automation step, request a registry payload file directly from the action:

permissions:
  contents: read

jobs: scan-plugin: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6

  - name: Scan plugin
    id: scan
    uses: hashgraph-online/ai-plugin-scanner-action@v1
    with:
      plugin_dir: &quot;.&quot;
      format: sarif
      output: ai-plugin-scanner.sarif
      registry_payload_output: ai-plugin-registry-payload.json

  - name: Show trust signals
    run: |
      echo &quot;Score: ${{ steps.scan.outputs.score }}&quot;
      echo &quot;Grade: ${{ steps.scan.outputs.grade_label }}&quot;
      echo &quot;Max severity: ${{ steps.scan.outputs.max_severity }}&quot;

  - name: Upload registry payload
    uses: actions/upload-artifact@v6
    with:
      name: ai-plugin-registry-payload
      path: ${{ steps.scan.outputs.registry_payload_path }}

The registry payload mirrors the submission data used by HOL ecosystem automation, so one scan can drive code scanning, review summaries, awesome-list intake, and registry trust ingestion.

Development

pip install -e ".[dev]"
ruff check src tests
ruff format --check src
pytest -q
python -m build

Repository Workflows

  • Matrix CI for Python 3.10 through 3.13
  • Package publishing via the publish.yml workflow
  • OpenSSF Scorecard automation for repository hardening visibility

Security

For disclosure and response policy, see SECURITY.md.

Contributing

Contribution guidance lives in CONTRIBUTING.md.

Maintainers

Maintained by HOL.

Example: HOL Registry Broker Plugin

The HOL Registry Broker Codex Plugin bridges Codex plugins with the HOL Universal Registry, providing agent discovery, trust signals, and verified identity on Hedera.

Registry Broker trust badge

HOL Registry scores: Trust 80 / Review 83 / Enforce 74

🔗 Plugin Scanner v2.0.0
Scanning: ./registry-broker-codex-plugin

── Manifest Validation (31/31) ── ✅ plugin.json exists +4 ✅ Valid JSON +4 ✅ Required fields present +5 ✅ Version follows semver +3 ✅ Name is kebab-case +2 ✅ Recommended metadata present +4 ✅ Interface metadata complete if declared +3 ✅ Interface links and assets valid if declared +3 ✅ Declared paths are safe +3

── Security (24/24) ── ✅ SECURITY.md found +3 ✅ LICENSE found +3 ✅ No hardcoded secrets +7 ✅ No dangerous MCP commands +3 ✅ MCP remote transports are hardened +3 ✅ No approval bypass defaults +5

── Operational Security (20/20) ── ✅ Third-party GitHub Actions pinned to SHAs +5 ✅ No write-all GitHub Actions permissions +5 ✅ No privileged untrusted checkout patterns +3 ✅ Dependabot configured for automation surfaces +4 ✅ Dependency manifests have lockfiles +3

── Best Practices (15/15) ── ✅ README.md found +5 ✅ Skills directory present +3 ✅ SKILL.md frontmatter valid +4 ✅ No committed .env +2 ✅ .codexignore found +1

── Marketplace (15/15) ── ✅ marketplace.json valid +5 ✅ Policy fields present +5 ✅ Marketplace sources are safe +5

── Skill Security (15/15) ── ✅ Cisco skill scan completed +3 ✅ No elevated Cisco skill findings +8 ✅ Skills analyzable +4

── Code Quality (10/10) ── ✅ No eval or Function constructor +5 ✅ No shell injection patterns +5

Findings: critical:0, high:0, medium:0, low:0, info:0

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Final Score: 130/130 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Plugins that pass the scanner with a high score are candidates for listing in the HOL Plugin Registry.

Resources

License

Apache-2.0

SEE ALSO

clihub4/13/2026AI-PLUGIN-SCANNER(1)