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).
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 / 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.
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”.
security_review.py inventory --dir <project> --json → know exactly which lockfiles exist and which tool applies.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).classify so 1 = findings, 2+ = infra error.normalize --tool <t> --input <scanner.json> → unified findings (ruleId/rule/level/message/path/line/col).secret-scanner skill for credentials/tokens.inventory lists every lockfile in the target directory with correct ecosystem + suggested tool.classify --exit-code matches the verified table above for your installed tools.normalize produces a valid unified report for the 5 built-in formats (osv-scanner, pip-audit, semgrep, gitleaks, bandit).1 on real findings, EXIT_NEUTRAL (or 2) on infra errors, clean on 0.