Skip to main content

Security scanner for AI agent skills and instruction artifacts

Project description

skill-scanner

CI Publish TestPyPI Publish PyPI zizmor License PyPI Security Policy

skill-scanner reviews AI skill and instruction artifacts for security risk using:

  • OpenAI analysis
  • VirusTotal analysis

Requirements

  • Python 3.11+
  • uv
  • OpenAI and/or VirusTotal API key (at least one)

Install (from source)

uv sync --all-extras --group dev

Run with:

uv run skill-scanner --help

Alias:

uv run skillscan --help

What gets scanned

By default, discover and scan detect markdown-based skill/instruction artifacts (for example SKILL.md, AGENTS.md, CLAUDE.md, *.instructions.md, *.prompt.md, *.agent.md, .mdc).

Validated skill locations also include:

  • Windsurf: .windsurf/skills/*/SKILL.md, ~/.codeium/windsurf/skills/*/SKILL.md
  • Gemini CLI: .gemini/skills/*/SKILL.md, ~/.gemini/skills/*/SKILL.md (.agents/skills/*/SKILL.md when --platform gemini)
  • Cline: .cline/skills/*/SKILL.md, .clinerules/skills/*/SKILL.md, ~/.cline/skills/*/SKILL.md, ~/.clinerules/skills/*/SKILL.md
  • OpenCode: .opencode/skills/*/SKILL.md, ~/.config/opencode/skills/*/SKILL.md (.agents/skills/*/SKILL.md and .claude/skills/*/SKILL.md when --platform opencode)
  • Claude marketplace/user variants: .claude/skills/SKILL.md, .claude/skills/*/SKILL.md, and .claude/plugins/marketplaces/*/{plugins,external_plugins}/*/skills/*/SKILL.md
  • Documented agent profile locations: .claude/agents/*.md, .gemini/agents/*.md, .gemini/extensions/*/agents/*.md, .opencode/agents/*.md, ~/.config/opencode/agents/*.md, .github/agents/**/*.agent.md, and agents/*.agent.md
  • Skill discovery supports both flat and nested layouts: skills/SKILL.md and skills/<name>/SKILL.md

Use --path to target a specific file or folder. --path discovery is deterministic and only emits files that match known discovery roots/patterns (plus a direct SKILL.md at the provided path root). It does not treat arbitrary *.md files as targets.

Default discover behavior:

  • discover attempts all scopes (repo, user, system, extension).
  • repo scope is only active when your current directory is inside a git repository.
  • Filesystem traversal errors are non-fatal; discovery returns partial results. Use --verbose to inspect warnings.

Quick start

# See targets
uv run skill-scanner discover --format json

# Discover only user scope
uv run skill-scanner discover --scope user

# Show detailed discovery warnings
uv run skill-scanner discover --verbose

# Verify key/model configuration
uv run skill-scanner doctor

# Run live API checks (fails non-zero if checks fail)
uv run skill-scanner doctor --check

# Run a combined scan (if both keys are configured)
uv run skill-scanner scan --format summary

Key configuration and analyzer selection

scan requires at least one analyzer enabled.

  • If only OPENAI_API_KEY is available, AI runs and VT is disabled.
  • If only VT_API_KEY is available, VT runs and AI is disabled.
  • If both keys are available, VT findings are included and VT context is passed into AI analysis.
  • You can disable either analyzer with --no-ai or --no-vt.
  • If no model is configured, gpt-5.2 is used as a fallback model.

Use doctor --check to verify the provider/key/model connectivity.

API key safety

Use 1Password secret references instead of plaintext secrets:

OPENAI_API_KEY=op://Developer/OpenAI/api_key
VT_API_KEY=op://Developer/VirusTotal/api_key

Run the scanner through 1Password CLI so references are resolved at runtime:

op run --env-file=.env -- uv run skill-scanner scan --format summary

Security best practice:

  • Prefer a 1Password Service Account scoped to only the vault/items required for scanning (least privilege).

Reference:

Output formats

scan --format supports:

  • table (default)
  • summary
  • json
  • sarif

You can write output to a file with --output <path>.

Useful commands

# List providers
uv run skill-scanner providers

# Scan one path only
uv run skill-scanner scan --path ./some/skill/folder --format summary

# Increase scan concurrency (default: 8)
uv run skill-scanner scan --jobs 16 --format summary

# Enable verbose logs for troubleshooting
uv run skill-scanner scan --verbose --format summary

# List discovered targets without running analyzers
uv run skill-scanner scan --list-targets

# Discover targets from user scope only
uv run skill-scanner discover --scope user --format table

# Discover with detailed traversal diagnostics
uv run skill-scanner discover --verbose --format table

# Scan only selected discovered targets (repeat --target)
uv run skill-scanner scan --target /absolute/path/to/SKILL.md --target /absolute/path/to/AGENTS.md --format summary

# Filter to medium+
uv run skill-scanner scan --min-severity medium --format summary

# Non-zero exit if high+ findings exist
uv run skill-scanner scan --fail-on high --format summary

# Verbose doctor checks
uv run skill-scanner doctor --check --verbose

--list-targets can be used without API keys because it only runs discovery and exits.

Discovery troubleshooting (macOS/Windows)

# macOS/Windows: default discover should complete without crashing
uv run skill-scanner discover --format table

# Scoped check: verify user skill paths only
uv run skill-scanner discover --scope user --format table

Windows known-path sanity check:

  • create %USERPROFILE%\\.clinerules\\skills\\demo\\SKILL.md
  • run uv run skill-scanner discover --platform cline --scope user --format table
  • confirm the demo skill appears in output

Exit behavior

  • 0: scan completed and fail threshold not hit
  • 1: --fail-on threshold matched
  • 2: no analyzers enabled (for example missing keys combined with flags), or --target did not match any discovered target

doctor --check exit behavior:

  • 0: all executed checks passed
  • 1: one or more checks failed

Notes and truncation visibility

scan now surfaces per-target notes in table and summary output, including:

  • analyzer failures (OpenAI or VirusTotal)
  • payload truncation when files are skipped due to the 400k-character AI payload limit
  • unreadable files excluded from payload construction

Version bump workflow

Use uv version so version updates stay command-driven and lock state remains consistent.

# Patch bump (e.g., 0.1.2 -> 0.1.3)
uv version --bump patch

# Or set an explicit version
uv version 0.2.0

Notes:

  • pyproject.toml is the canonical version source.
  • uv.lock is generated by uv and should not be edited manually.

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

skill_scanner-0.2.1.tar.gz (138.2 kB view details)

Uploaded Source

Built Distribution

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

skill_scanner-0.2.1-py3-none-any.whl (38.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: skill_scanner-0.2.1.tar.gz
  • Upload date:
  • Size: 138.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for skill_scanner-0.2.1.tar.gz
Algorithm Hash digest
SHA256 60f8e544149e3f452ca8060e00cf2b7eb70057bf3e1f1113ed3d00a90dcb7ede
MD5 30d1cb26b3dad07cc06f8cbf295e84c5
BLAKE2b-256 9ca1979ff65ccd043094b8fedf44f8fd3526c67d50d42dbb4a400e2110af94c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for skill_scanner-0.2.1.tar.gz:

Publisher: release.yml on thedevappsecguy/skill-scanner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: skill_scanner-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 38.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for skill_scanner-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 26c9ab72e26af56d9ba6ddc7c22232d369f54337fbb37e1176c210f9efb1a5c8
MD5 36652c1ce8d8d813162c32d8df10b8b4
BLAKE2b-256 d31d55265b9cde8b55c75af0289f0d8909f5bce1fdd60d9128576bc3db259241

See more details on using hashes here.

Provenance

The following attestation bundles were made for skill_scanner-0.2.1-py3-none-any.whl:

Publisher: release.yml on thedevappsecguy/skill-scanner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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