![]() |
Security, publishability, and security-ops scanner for Codex plugins. It scores the applicable plugin surface from 0-100, emits structured findings, validates install-surface metadata, hardens MCP transport expectations, and can run Cisco-backed skill analysis for plugin skills.PyPI Package HOL GitHub Repository Report an Issue |
|---|
git clone https://github.com/hashgraph-online/codex-plugin-scanner.git
cd codex-plugin-scanner
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest -qpip install codex-plugin-scannerCisco-backed skill scanning is optional:
pip install "codex-plugin-scanner[cisco]"You can also run the scanner without a local install:
pipx run codex-plugin-scanner ./my-pluginThe 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.
| Category | Max Points | Coverage |
|---|---|---|
| Manifest Validation | 31 | plugin.json, required fields, semver, kebab-case, recommended metadata, interface metadata, interface links and assets, safe declared paths |
| Security | 24 | SECURITY.md, LICENSE, hardcoded secret detection, dangerous MCP commands, MCP transport hardening, risky approval defaults |
| Operational Security | 20 | SHA-pinned GitHub Actions, write-all, privileged untrusted checkout patterns, Dependabot, dependency lockfiles |
| Best Practices | 15 | README.md, skills directory, SKILL.md frontmatter, committed .env, .codexignore |
| Marketplace | 15 | marketplace.json validity, policy fields, safe source paths |
| Skill Security | 15 | Cisco integration status, elevated skill findings, analyzability |
| Code Quality | 10 | eval, new Function, shell-injection patterns |
# Scan a plugin directory
codex-plugin-scanner ./my-plugin
# Output JSON
codex-plugin-scanner ./my-plugin --json
# Write a SARIF report for GitHub code scanning
codex-plugin-scanner ./my-plugin --format sarif --output codex-plugin-scanner.sarif
# Fail CI on findings at or above high severity
codex-plugin-scanner ./my-plugin --fail-on-severity high
# Require Cisco skill scanning with a strict policy
codex-plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strictπ Codex Plugin Scanner v1.2.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)
βββββββββββββββββββββββββββββββββββββ
| Format | Use Case |
|---|---|
text |
Human-readable terminal summary with category totals and findings |
json |
Structured integrations and findings for tooling and dashboards |
markdown |
Pull request, issue, or review-ready summaries |
sarif |
GitHub code scanning uploads and security automation |
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 orcmd /cshells - 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
interfacemetadata, 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-scannerwhen the optional integration is installed
Add the scanner to a plugin repository CI job:
- name: Install scanner
run: pip install codex-plugin-scanner
- name: Scan plugin
run: codex-plugin-scanner ./my-plugin --fail-on-severity high --format sarif --output codex-plugin-scanner.sarif
continue-on-error: trueLocal pre-commit style hook:
repos:
- repo: local
hooks:
- id: codex-plugin-scanner
name: Codex Plugin Scanner
entry: codex-plugin-scanner
language: system
types: [directory]
pass_filenames: false
args: ["./"]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.
The source repository can publish the GitHub Action automatically into a dedicated public action repository.
Configure:
- repository secret
ACTION_REPO_TOKENIt should be a token that can create or update repositories and releases in the target repository. - optional repository variable
ACTION_REPOSITORYDefaults tohashgraph-online/hol-codex-plugin-scanner-action.
When a tagged release is published, publish-action-repo.yml will:
- create the dedicated action repository if it does not already exist
- sync the root-ready
action.yml,README.md,LICENSE, andSECURITY.md - push the immutable release tag such as
v1.2.0 - move the floating
v1tag - create or update the corresponding release in the 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.
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 Codex-friendly machine outputs:
score,grade,grade_label,max_severity, andfindings_totalas 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:
- Add the scanner action to plugin CI.
- Require
min_score: 80and a severity gate such asfail_on_severity: high. - Enable submission mode with a token that has
issues:writeonhashgraph-online/awesome-codex-plugins. - When the plugin clears the threshold, the action opens or reuses a submission issue.
- 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/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
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 == 'true'
run: echo "${{ steps.scan.outputs.submission_issue_urls }}"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.
If you want to feed the same scan into a registry, badge pipeline, or another Codex 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/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
format: sarif
output: codex-plugin-scanner.sarif
registry_payload_output: codex-plugin-registry-payload.json
- name: Show trust signals
run: |
echo "Score: ${{ steps.scan.outputs.score }}"
echo "Grade: ${{ steps.scan.outputs.grade_label }}"
echo "Max severity: ${{ steps.scan.outputs.max_severity }}"
- name: Upload registry payload
uses: actions/upload-artifact@v6
with:
name: codex-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.
pip install -e ".[dev]"
ruff check src tests
ruff format --check src
pytest -q
python -m build- Matrix CI for Python
3.10through3.13 - Package publishing via the
publish.ymlworkflow - OpenSSF Scorecard automation for repository hardening visibility
For disclosure and response policy, see SECURITY.md.
Contribution guidance lives in CONTRIBUTING.md.
Maintained by HOL.
- OpenAI Codex Plugin Documentation
- Model Context Protocol Documentation
- Cisco AI Skill Scanner
- HOL GitHub Organization
Apache-2.0
# Summary scan (legacy form still works)
codex-plugin-scanner scan ./my-plugin --format json --profile public-marketplace
# Rule-oriented lint (with optional mechanical fixes)
codex-plugin-scanner lint ./my-plugin --list-rules
codex-plugin-scanner lint ./my-plugin --explain README_MISSING
codex-plugin-scanner lint ./my-plugin --fix --profile strict-security
# Runtime readiness verification
codex-plugin-scanner verify ./my-plugin --format json
# Artifact-backed submission gate
codex-plugin-scanner submit ./my-plugin --profile public-marketplace --attest dist/plugin-quality.json
# Diagnostic bundle
codex-plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip# .codex-plugin-scanner.toml
[scanner]
profile = "public-marketplace"
baseline_file = "baseline.txt"
ignore_paths = ["tests/*", "fixtures/*"]
[rules]
disabled = ["README_MISSING"]
severity_overrides = { CODEXIGNORE_MISSING = "low" }