Agent Skills

Security Review — dependency & static analysis orchestration

Load this skill when you need to run a security review of a codebase: audit the dependency manifest/lockfile inventory, decide which scanner to run per ecosystem, interpret scanner exit codes correctly (real findings vs. infrastructure errors), and normalize reports from different tools into one unified schema for a final report.

The helper script is offline by design — it inventories, classifies, and normalizes. Actual scans are executed by the well-known external tools listed below (install once locally or in CI).


The helper script

scripts/security_review.py — pure Python 3 stdlib (no dependencies).

Command Purpose
security_review.py inventory --dir . List dependency locks with ecosystem + suggested tool
security_review.py inventory --dir . --json Same, machine-readable
security_review.py classify --tool semgrep --exit-code 1 Explain what a tool exit code means
security_review.py normalize --tool osv-scanner --input out.json Flatten a tool JSON report into unified findings
security_review.py normalize --tool pip-audit --input pip.json --output report.json Save unified report
security_review.py report --root . Report skeleton (markdown default, --json for JSON)

Lockfile inventory (per-ecosystem suggested tool)

Lockfile / manifest Ecosystem Suggested tool
package-lock.json, pnpm-lock.yaml, yarn.lock npm / pnpm / yarn npm audit / osv-scanner
requirements*.txt, pyproject.toml, Pipfile.lock, poetry.lock pip pip-audit
Cargo.lock cargo cargo audit
go.mod, go.sum go osv-scanner
Gemfile.lock gem osv-scanner
pom.xml, build.gradle(.kts) maven / gradle osv-scanner / dependency-check
composer.lock composer osv-scanner

package.json alone (no lockfile) is still reported, so gate or scan it with npm audit.


Exit-code semantics (verified August 2026)

Get each tool’s meaning on the fly with classify --tool X --exit-code N.

Tool 0 findings error / other
semgrep clean 1 (findings) 2 fatal; 3/4/5/7/8/13/99 specific errors
bandit clean 1 (issues) 2 error
gitleaks clean 1 (leaks or error) 126 unknown flag
pip-audit clean 1 (vulns)
osv-scanner v2 clean 1 (vulns) 127 error, 128 no packages, 129 API failed, 130 config
npm audit clean 1 (vulns)
cargo audit clean non-zero (vulns / errors)
grype clean 2 (vulns ≥ fail-on) 1 error, 100 DB update
truffle clean 183 (findings, only with --fail) 1 error
checkov clean 1 (failed checks) 2 error
trivy clean 1 (vulns, with --exit-code)
dependency-check clean 1 (vulns ≥ threshold)

Rule of thumb: exit 0 == “no findings” only for tools listed as clean=0; other codes are infra errors and must not be treated as “vulnerable”.


Workflow

  1. Inventorysecurity_review.py inventory --dir <project> --json → know exactly which lockfiles exist and which tool applies.
  2. Scan — run the suggested tool per row above with its JSON format (see references/canonical-patterns.md for exact CLI + JSON shapes; e.g. semgrep JSON with --json, osv-scanner --json, pip-audit --format json, gitleaks --report-format json, bandit -f json).
  3. Classify exits — in CI, map exit codes via classify so 1 = findings, 2+ = infra error.
  4. Normalizenormalize --tool <t> --input <scanner.json> → unified findings (ruleId/rule/level/message/path/line/col).
  5. Report — merge all normalized findings into one report (markdown or JSON), present severity rollup.

When NOT to use

Success criteria