Cisco Skill Scanner integrates with CI/CD pipelines, pre-commit hooks, and GitHub Code Scanning.
Repository workflows under .github/workflows/:
- python-tests.yml -- lint, test matrix, coverage, security checks
- integration-tests.yml -- external API-backed integration suites
- release.yml -- PyPI publish flow
Add a scan step to your existing workflow:
- name: Scan agent skills
run: |
pip install cisco-ai-skill-scanner
skill-scanner scan-all ./skills --fail-on-findingsGenerate SARIF output and upload it to GitHub's security tab:
name: Skill Security Scan
on:
push:
branches: [main]
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Skill Scanner
run: pip install cisco-ai-skill-scanner
- name: Run scan
run: |
skill-scanner scan-all ./skills \
--recursive \
--format sarif \
--output results.sarif \
--fail-on-findings
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarifFor deeper semantic analysis, add API keys as repository secrets:
- name: Run scan with LLM
env:
SKILL_SCANNER_LLM_API_KEY: ${{ secrets.SKILL_SCANNER_LLM_API_KEY }}
SKILL_SCANNER_LLM_MODEL: anthropic/claude-sonnet-4-20250514
run: |
skill-scanner scan-all ./skills \
--recursive \
--use-behavioral \
--use-llm \
--enable-meta \
--format sarif \
--output results.sarif \
--fail-on-findingsSkill Scanner provides a pre-commit hook that scans skills before each commit.
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/cisco-ai-defense/skill-scanner
rev: v1.0.0 # use latest version
hooks:
- id: skill-scanner
args: ["--fail-on-findings"]# Copy the hook script
cp scripts/pre-commit-hook.sh .git/hooks/pre-commit
chmod +x .git/hooks/pre-commitThe hook entry point is skill-scanner-pre-commit, which is installed alongside the main CLI.
There is no staged index to inspect after a CI checkout. Use pre-commit's revision comparison; the hook reads those revisions from pre-commit's environment and computes the changed paths internally:
pre-commit run skill-scanner \
--from-ref "$BASE_SHA" \
--to-ref "$HEAD_SHA"The hook uses a separate deletion diff so removed paths are included, resolves
each changed path to its nearest parent containing SKILL.md, and scans each
affected skill once. Both revisions must be present locally; configure the
checkout step to fetch enough history for the selected base and head SHAs.
Keep preset strategy explicit by workflow stage:
- Pull requests:
balancedorstrictpreset for fast feedback - Nightly / security sweep:
strict+ optional semantic analyzers (--use-llm,--use-behavioral)
Use --fail-on-findings to fail CI builds when critical or high severity findings are detected:
skill-scanner scan /path/to/skill --fail-on-findingsExit codes:
- 0 — No critical/high findings
- 1 — Critical or high findings detected (build should fail)
Choose the right format for your integration. See Output Formats Reference for sample outputs and a format decision guide.
| Format | Use Case | Flag |
|---|---|---|
summary |
Terminal output, human review | --format summary (default) |
json |
Programmatic processing, APIs | --format json |
sarif |
GitHub Code Scanning, IDE integration | --format sarif |
markdown |
Pull request comments, reports | --format markdown |
table |
Terminal dashboards | --format table |
html |
Interactive reports with correlation groups | --format html |
All formats support output to file:
skill-scanner scan /path/to/skill --format json --output results.json
skill-scanner scan /path/to/skill --format html --output report.htmlFor programmatic integration:
from skill_scanner import SkillScanner
from skill_scanner.core.analyzers import BehavioralAnalyzer
scanner = SkillScanner(analyzers=[
BehavioralAnalyzer(),
])
result = scanner.scan_skill("/path/to/skill")
print(f"Findings: {len(result.findings)}")
print(f"Max severity: {result.max_severity}")
if not result.is_safe:
print("Issues detected — review findings before deployment")Skill Scanner also provides a FastAPI-based REST API for service-to-service integration:
skill-scanner-api --host 0.0.0.0 --port 8000See the REST API documentation for endpoints and usage.
For service-style scanning, use the /scan-upload or /scan-batch endpoints from the running API server instead of invoking the CLI:
- name: Scan via API
run: |
curl -s -X POST http://localhost:8000/scan \
-H "Content-Type: application/json" \
-d '{"skill_directory": "./skills/my-skill"}' \
-o result.json
# Fail if any critical/high findings
python -c "
import json, sys
r = json.load(open('result.json'))
if r.get('max_severity') in ('CRITICAL', 'HIGH'):
print('Findings detected'); sys.exit(1)
"This pattern is useful when the scanner runs as a long-lived service (e.g., in a sidecar container) and you want to avoid cold-start overhead per CI job.