A best-effort security scanner for AI Agent Skills that detects prompt injection, data exfiltration, and malicious code patterns.
$ npx -y skills add cisco-ai-defense/skill-scanner --agent claude-code
Run the curl in your terminal, the rest in Claude Code.
What's inside
A best-effort security scanner for AI Agent Skills that detects prompt injection, data exfiltration, and malicious code patterns. Combines pattern-based detection (YAML + YARA), LLM-as-a-judge, and behavioral dataflow analysis to maximize detection coverage of probable threats while minimizing false positives.
Important: This scanner provides best-effort detection, not comprehensive or complete coverage. A scan that returns no findings does not guarantee that a skill is free of all threats. See Scope and Limitations below.
Supports OpenAI Codex Skills and Cursor Agent Skills formats following the Agent Skills specification. With --lenient, also scans non-standard formats such as Claude Code .claude/commands/*.md and flat markdown skill repos.
Join the Cisco AI Discord to discuss, share feedback, or connect with the team.
Skill Scanner is a detection tool. It identifies known and probable risk patterns, but it does not certify security.
Key limitations:
| Guide | Description |
|---|---|
| Quick Start | Get started in 5 minutes |
| Architecture | System design and components |
| Threat Taxonomy | Complete AITech threat taxonomy with examples |
| LLM Analyzer | LLM configuration and usage |
| Meta-Analyzer | False positive filtering and prioritization |
| Behavioral Analyzer | Dataflow analysis details |
| Scan Policy | Custom policies, presets, and tuning guide |
| Policy Quick Reference | Compact reference for policy sections and knobs |
| Rule Authoring | How to add signature, YARA, and Python rules |
| GitHub Actions | Reusable workflow for CI/CD integration |
| API Reference | REST API documentation |
| Development Guide | Contributing and development setup |
Prerequisites: Python 3.10+ and uv (recommended) or pip
# Using uv (recommended)
uv pip install cisco-ai-skill-scanner
# Using pip
pip install cisco-ai-skill-scanner
# AWS Bedrock support
pip install cisco-ai-skill-scanner[bedrock]
# Google AI Studio / Gemini support
pip install cisco-ai-skill-scanner[google]
# Google Vertex AI support
pip install cisco-ai-skill-scanner[vertex]
# Azure OpenAI support
pip install cisco-ai-skill-scanner[azure]
# All cloud providers
pip install cisco-ai-skill-scanner[all]
# For LLM analyzer and Meta-analyzer
export SKILL_SCANNER_LLM_API_KEY="your_api_key"
export SKILL_SCANNER_LLM_MODEL="claude-3-5-sonnet-20241022"
# For VirusTotal binary scanning
export VIRUSTOTAL_API_KEY="your_virustotal_api_key"
# For Cisco AI Defense
export AI_DEFENSE_API_KEY="your_aidefense_api_key"
Not sure which flags to use? Run skill-scanner with no arguments to launch the interactive wizard:
skill-scanner
The wizard walks you through selecting a scan target, analyzers, policy, and output format, then shows the assembled command before running it. Great for learning the CLI.
# Scan a single skill (core analyzers: static + bytecode + pipeline)
skill-scanner scan /path/to/skill
# Scan with behavioral analyzer (dataflow analysis)
skill-scanner scan /path/to/skill --use-behavioral
# Scan with all engines
skill-scanner scan /path/to/skill --use-behavioral --use-llm --use-aidefense
# Scan with meta-analyzer for false positive filtering
skill-scanner scan /path/to/skill --use-llm --enable-meta
# Scan with trigger analyzer for vague description checks
skill-scanner scan /path/to/skill --use-trigger
# Run LLM analyzer multiple times and keep majority-agreed findings
skill-scanner scan /path/to/skill --use-llm --llm-consensus-runs 3
# Scan multiple skills recursively
skill-scanner scan-all /path/to/skills --recursive --use-behavioral
# Scan multiple skills with cross-skill overlap detection
skill-scanner scan-all /path/to/skills --recursive --check-overlap
# Scan a GitHub repository (owner/repo shorthand or full URL)
skill-scanner scan-repo owner/repo
skill-scanner scan-repo https://github.com/owner/repo --use-llm
# Lenient mode: tolerate malformed skills instead of failing
skill-scanner scan /path/to/skill --lenient
skill-scanner scan-all /path/to/skills --recursive --lenient
# Lenient mode with non-standard skill formats (no SKILL.md required)
skill-scanner scan .claude/commands/deploy --lenient
skill-scanner scan-all .claude/commands --recursive --lenient
# Use a custom metadata filename instead of SKILL.md
skill-scanner scan /path/to/skill --skill-file README.md
# CI/CD: Fail build if threats found
skill-scanner scan-all ./skills --fail-on-severity high --format sarif --output results.sarif
# Generate interactive HTML report with attack correlation groups
skill-scanner scan /path/to/skill --use-llm --enable-meta --format html --output report.html
# Use custom YARA rules
skill-scanner scan /path/to/skill --custom-rules /path/to/my-rules/
# Use custom taxonomy + threat mapping profiles (JSON/YAML)
skill-scanner scan /path/to/skill --taxonomy /path/to/taxonomy.json --threat-mapping /path/to/threat_mapping.json
# VirusTotal hash scan with optional unknown-file uploads
skill-scanner scan /path/to/skill --use-virustotal --vt-upload-files
# Use a scan policy preset (strict, balanced, permissive)
skill-scanner scan /path/to/skill --policy strict
# Use a custom org policy file
skill-scanner scan /path/to/skill --policy my_org_policy.yaml
# Generate a policy file to customise
skill-scanner generate-policy -o my_org_policy.yaml
# Interactive policy configurator (TUI)
skill-scanner configure-policy
Consensus mode keeps a finding only when it appears in more than half of the configured runs. When those votes disagree on severity, the highest observed severity wins, independent of response order. Failed runs and successful runs that omit the finding cast no vote but remain in the denominator. This makes severity selection stable for majority-agreed findings. It does not make an individual LLM sample deterministic, and descriptive fields from equal-severity votes, single-run output, and non-majority findings can still vary between scans.
LLM provider note: --llm-provider currently accepts anthropic or openai.
For Bedrock, Vertex, Azure, Gemini, and other LiteLLM backends, set provider-specific model strings and environment variables (see LLM Analyzer docs).
from skill_scanner import SkillScanner
from skill_scanner.core.analyzers import BehavioralAnalyzer
# Create scanner with analyzers
scanner = SkillScanner(analyzers=[
BehavioralAnalyzer(),
])
# Scan a skill
result = scanner.scan_skill("/path/to/skill")
print(f"Findings: {len(result.findings)}")
print(f"Max severity: {result.max_severity}")
# Note: is_safe indicates no HIGH/CRITICAL findings were detected.
# It does not guarantee the skill is free of all risk.
if not result.is_safe:
print("Issues detected -- review findings before deployment")
| Analyzer | Detection Method | Scope | Requirements |
|---|---|---|---|
| Static | YAML + YARA patterns | All files | None |
| Bytecode | .pyc integrity verification | Python bytecode | None |
| Pipeline | Command taint analysis | Shell pipelines | None |
| Behavioral | AST dataflow analysis | Python files | None |
| LLM | Semantic analysis | SKILL.md + scripts | API key |
| Meta | False positive filtering | All findings | API key |
| VirusTotal | Hash-based malware | Binary files | API key |
| AI Defense | Cloud-based AI | Text content | API key |
| Option | Description |
|---|---|
--policy | Scan policy: preset name (strict, balanced, permissive) or path to custom YAML |
--use-behavioral | Enable behavioral analyzer (dataflow analysis) |
--use-llm | Enable LLM analyzer (requires API key) |
--llm-provider | LLM provider for CLI routing: anthropic or openai |
--llm-consensus-runs N | Run LLM analysis N times, keep majority-agreed findings, and retain their highest observed severity |
--llm-max-tokens N | Maximum output tokens for LLM responses (default: 8192) |
--use-virustotal | Enable VirusTotal binary scanner |
--vt-api-key KEY | Provide VirusTotal API key directly (optional) |
--vt-upload-files | Upload unknown binaries to VirusTotal (optional) |
--use-aidefense | Enable Cisco AI Defense analyzer |
--aidefense-api-url URL | Override AI Defense API URL (optional) |
--use-trigger | Enable trigger specificity analyzer |
--enable-meta | Enable meta-analyzer for false positive filtering |
--verbose | Include per-finding policy fingerprints, co-occurrence metadata, and keep meta-analyzer false positives |
--format | Output: summary, json, markdown, table, sarif, html. The html format produces a self-contained interactive report with collapsible correlation groups, expandable code snippets, and pipeline taint flow diagrams |
--detailed | Include detailed findings in Markdown output |
--compact | Compact JSON output |
--output PATH | Default output file path (overridden by --output-<fmt>) |
--fail-on-findings | Exit with error if HIGH/CRITICAL found (shorthand for --fail-on-severity high) |
--fail-on-severity LEVEL | Exit with error if findings at or above LEVEL exist (critical, high, medium, low, info) |
--custom-rules PATH | Use custom YARA rules from directory |
--taxonomy PATH | Load custom taxonomy profile (JSON/YAML) for this run |
--threat-mapping PATH | Load custom scanner threat mapping profile (JSON) for this run |
--lenient | Tolerate malformed skills (coerce bad fields, fill defaults) instead of failing. When SKILL.md is absent, falls back to scanning .md files in the directory |
--skill-file FILENAME | Custom metadata filename to use instead of SKILL.md (e.g. README.md) |
--check-overlap | (scan-all) Enable cross-skill description overlap checks |
| Command | Description |
|---|---|
| (no command) | Launch interactive scan wizard (when run in a terminal) |
interactive | Launch interactive scan wizard (explicit) |
scan | Scan a single skill directory |
scan-all | Scan multiple skills (with --recursive, --check-overlap) |
generate-policy | Generate a scan policy YAML for customisation |
configure-policy | Interactive TUI to build/edit a custom scan policy (--input supported) |
list-analyzers | Show available analyzers |
validate-rules | Validate rule signatures (--rules-file supported) |
$ skill-scanner scan ./my-skill --use-behavioral
============================================================
Skill: my-skill
============================================================
Status: [OK] No findings
Max Severity: NONE
Total Findings: 0
Scan Duration: 0.15s
Note: "No findings" means the scanner did not detect any known threat patterns -- it is not a guarantee that the skill is free of all risk. See Scope and Limitations.
Scan skills automatically on every push or PR using the reusable workflow:
# .github/workflows/scan-skills.yml
name: Scan Skills
on:
pull_request:
paths: [".cursor/skills/**"]
jobs:
scan:
uses: cisco-ai-defense/skill-scanner/.github/workflows/scan-skills.yml@main
with:
skill_path: .cursor/skills
permissions:
security-events: write
contents: read
Results appear as inline annotations in PRs via GitHub Code Scanning. See the full guide for LLM integration, secret configuration, and branch protection setup.
Scan skills before every commit using the pre-commit framework:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/cisco-ai-defense/skill-scanner
rev: v1.0.0 # use the latest release tag
hooks:
- id: skill-scanner
Or install the built-in hook directly:
skill-scanner-pre-commit --install
The hook maps changed files to their nearest SKILL.md and scans each affected
skill once. During a normal commit, it reads the staged diff. In CI, compare two
revisions so no staged index is required:
pre-commit run skill-scanner --from-ref "$BASE_SHA" --to-ref "$HEAD_SHA"
Both revisions must exist in the checkout. To scan every configured skill, invoke the hook directly:
skill-scanner-pre-commit --scan-all
Alternatively, configure args: [--scan-all] for the hook in
.pre-commit-config.yaml.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Apache 2.0 - See LICENSE for details.
Copyright 2026 Cisco Systems, Inc. and its affiliates
.cursor/
rules/
codeguard-0-additional-cryptography.mdc
codeguard-0-framework-and-languages.mdc
codeguard-0-iac-security.mdc
codeguard-0-mobile-apps.mdc
codeguard-0-supply-chain-security.mdc
codeguard-1-crypto-algorithms.mdc
codeguard-1-digital-certificates.mdc
codeguard-1-hardcoded-credentials.mdc
no-cursor-co-author.mdc
.devin/
wiki.json
.env.example
.github/
ISSUE_TEMPLATE/
bug_report.md
feature_request.md
PULL_REQUEST_TEMPLATE.md
workflows/
docs-site.yml
integration-tests.yml
python-tests.yml
release.yml
scan-skills.yml
update-homebrew.yml
.gitignore
.gitleaksignore
.pre-commit-config.yaml
.pre-commit-hooks.yaml
.windsurf/
rules/
codeguard-0-additional-cryptography.md
codeguard-0-framework-and-languages.md
codeguard-0-iac-security.md
codeguard-0-mobile-apps.md
codeguard-0-supply-chain-security.md
codeguard-1-crypto-algorithms.md
codeguard-1-digital-certificates.md
codeguard-1-hardcoded-credentials.md
CODE_OF_CONDUCT.md
CODEOWNERS
CONTRIBUTING.md
docs/
docs-site/
api-reference.mdx
architecture.mdx
cli-reference.mdx
faq.mdx
features.mdx
github-actions.mdx
index.mdx
installation.mdx
python-sdk.mdx
quick-start.mdx
README.md
scan-policies.mdx
architecture/
analyzers/
adjudicator.md
aidefense-analyzer.md
behavioral-analyzer.md
index.md
llm-analyzer.md
meta-analyzer.md
meta-and-external-analyzers.md
osv-analyzer.md
static-analyzer.md
writing-custom-rules.md
binary-handling.md
index.md
scanning-pipeline.md
threat-taxonomy.md
concepts/
remote-skills-analysis.md
security-model.md
development/
index.md
integrations.md
setup-and-testing.md
features/
index.md
getting-started/
quick-start.md
github-actions.md
guides/
examples-and-how-to.md
README.md
reference/
api-endpoint-reference.md
cli-command-reference.md
configuration-reference.md
dependencies-and-llm-providers.md
index.md
output-formats.md
policy-quick-reference.md
user-guide/
api-endpoints-detail.md
api-operations.md
api-rationale.md
api-server.md
cli-usage.md
custom-policy-configuration.md
index.md
installation-and-configuration.md
python-sdk.md
scan-policies-overview.md
evals/
__init__.py
policies/
01_baseline_no_policy.yaml
02_strict_preset.yaml
03_permissive_preset.yaml
04_compliance_audit.yaml
05_ci_pipeline.yaml
06_internal_tooling.yaml
07_no_pipeline_analysis.yaml
08_yara_wide_open.yaml
09_cred_heavy.yaml
10_max_sensitivity.yaml
README.md
runners/
__init__.py
benchmark_runner.py
eval_runner.py
policy_benchmark.py
update_expected_findings.py
skills/
backdoor/
magic-string-trigger/
_expected.json
process.py
SKILL.md
behavioral-analysis/
multi-file-exfiltration/
_expected.json
analyze.py
collector.py
encoder.py
reporter.py
SKILL.md
command-injection/
eval-execution/
_expected.json
calculate.py
SKILL.md
data-exfiltration/
config-tunnel-exfil/
_expected.json
config.yaml
SKILL.md
environment-secrets/
_expected.json
get_info.py
SKILL.md
obfuscation/
base64-payload/
_expected.json
process.py
SKILL.md
path-traversal/
file-reader/
_expected.json
read.py
SKILL.md
prompt-injection/
jailbreak-override/
_expected.json
SKILL.md
resource-exhaustion/
infinite-loop/
_expected.json
analyze.py
SKILL.md
safe-skills/
safe-skills-2/
file-validator/
_expected.json
SKILL.md
validate.py
simple-math/
_expected.json
math_ops.py
SKILL.md
sql-injection/
database-query/
_expected.json
query.py
SKILL.md
test_skills/
malicious/
ascii-smuggling/
SKILL.md
eicar-test/
_expected.json
assets/
test-binary.bin
SKILL.md
exfiltrator/
_expected.json
analyze.py
SKILL.md
flowise-cve-2025-59528/
SKILL.md
mcp-atlassian-cve-2026-27825/
SKILL.md
mcpwn-cve-2026-33032/
SKILL.md
prompt-injection/
SKILL.md
safe/
atr-benign-control/
SKILL.md
simple-formatter/
_expected.json
formatter.py
SKILL.md
examples/
__init__.py
advanced_scanning.py
api_usage.py
basic_scan.py
batch_scanning.py
behavioral_analyzer_example.py
custom-rule-pack/
pack.yaml
signatures.yaml
integration_example.py
llm_analyzer_example.py
programmatic_usage.py
FEATURE.md
Formula/
skill-scanner.rb
LICENSE
Makefile
pyproject.toml
README.md
scripts/
check_taxonomy.py
fp_analysis_collect.py
generate_reference_docs.py
pre-commit-hook.sh
update_brew_formula.py
validate_docs_site.py
SECURITY.md
skill_scanner/
__init__.py
api/
__init__.py
api_cli.py
api_server.py
api.py
router.py
cli/
__init__.py
cli.py
policy_tui.py
wizard.py
config/
__init__.py
config.py
constants.py
yara_modes.py
core/
__init__.py
analyzability.py
analyzer_factory.py
analyzers/
__init__.py
adjudicator.py
aidefense_analyzer.py
base.py
behavioral/
behavioral_analyzer.py
__init__.py
alignment/
__init__.py
alignment_llm_client.py
alignment_orchestrator.py
alignment_prompt_builder.py
alignment_response_validator.py
threat_vulnerability_classifier.py
bytecode_analyzer.py
cross_skill_scanner.py
llm_analyzer.py
llm_prompt_builder.py
llm_provider_config.py
llm_request_handler.py
llm_request_options.py
llm_response_parser.py
meta_analyzer.py
osv_analyzer.py
pipeline_analyzer.py
static.py
trigger_analyzer.py
virustotal_analyzer.py
changed_skills.py
command_safety.py
exceptions.py
extractors/
__init__.py
content_extractor.py
file_magic.py
loader.py
models.py
repo_fetcher.py
reporters/
__init__.py
html_reporter.py
json_reporter.py
markdown_reporter.py
sarif_reporter.py
table_reporter.py
rule_registry.py
rules/
__init__.py
patterns.py
yara_scanner.py
scan_policy.py
scanner.py
static_analysis/
__init__.py
bash_taint_tracker.py
cfg/
__init__.py
builder.py
context_extractor.py
dataflow/
__init__.py
forward_analysis.py
interprocedural/
__init__.py
call_graph_analyzer.py
cross_file_analyzer.py
parser/
__init__.py
python_parser.py
semantic/
__init__.py
name_resolver.py
type_analyzer.py
taint/
__init__.py
tracker.py
types/
__init__.py
url_classifier.py
strict_structure.py
data/
__init__.py
default_policy.yaml
packs/
__init__.py
atr/
pack.yaml
README.md
signatures/
atr_agent_manipulation.yaml
atr_context_exfiltration.yaml
atr_data_poisoning.yaml
atr_excessive_autonomy.yaml
atr_model_abuse.yaml
atr_model_security.yaml
atr_privilege_escalation.yaml
atr_prompt_injection.yaml
atr_skill_compromise.yaml
atr_tool_poisoning.yaml
core/
__init__.py
pack.yaml
python/
__init__.py
_helpers.py
allowed_tools_checks.py
analyzability_checks.py
archive_checks.py
ascii_smuggling_checks.py
asset_checks.py
binary_file_checks.py
bytecode_checks.py
consistency_checks.py
external_tool_checks.py
file_inventory_checks.py
hidden_file_checks.py
manifest_checks.py
trigger_checks.py
signatures/
command_injection.yaml
data_exfiltration.yaml
hardcoded_secrets.yaml
obfuscation.yaml
prompt_injection.yaml
resource_abuse.yaml
social_engineering.yaml
supply_chain.yaml
unauthorized_tool_use.yaml
yara/
autonomy_abuse_generic.yara
capability_inflation_generic.yara
code_execution_generic.yara
... 122 moreFAQ
skill-scanner is a Claude Code plugin with 12 hand-picked skills for security work, indexed on Flowy. Install it with the command on its page. It includes magic-string-trigger, multi-file-exfiltration, eval-execution. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.