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.
- Multi-Engine Detection - Static analysis, behavioral dataflow, LLM semantic analysis, and cloud-based scanning for layered, best-effort coverage
- False Positive Filtering - Meta-analyzer significantly reduces noise while preserving detection capability
- CI/CD Ready - SARIF output for GitHub Code Scanning, exit codes for build failures
- Extensible - Plugin architecture for custom analyzers
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:
- No findings ≠ no risk. A scan that returns "No findings" indicates that no known threat patterns were detected. It does not guarantee that a skill is secure, benign, or free of vulnerabilities.
- Coverage is inherently incomplete. The scanner combines signature-based detection, LLM-based semantic analysis, behavioral dataflow analysis, optional cloud services, and configurable rule packs. While this approach improve coverage, no automated tool can detect every technique, especially novel or zero-day attacks.
- False positives and false negatives can occur. Consensus modes and meta-analysis reduce noise, but no configuration eliminates all incorrect classifications. Tune the scan policy to your risk tolerance.
- Human review remains essential. Automated scanning is one component of a defense-in-depth strategy. High-risk or production deployments should pair scanner results with manual code review and/or threat modeling.
| 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 |
| 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-scannerCloud Provider Extras
# AWS Bedrock support
pip install cisco-ai-skill-scanner[bedrock]
# 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"# 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
# CI/CD: Fail build if threats found
skill-scanner scan-all ./skills --fail-on-findings --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-policyLLM 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 docs/llm-analyzer.md).
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 and keep majority-agreed findings |
--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 |
Save report to file |
--fail-on-findings |
Exit with error if HIGH/CRITICAL found |
--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 |
--check-overlap |
(scan-all) Enable cross-skill description overlap checks |
| Command | Description |
|---|---|
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.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Apache 2.0 - See LICENSE for details.
Copyright 2026 Cisco Systems, Inc. and its affiliates