Runs dead-dependency analysis across JS, Python, and Rust projects using ecosystem-native static tools (`depcheck`/`knip` for JS, `vulture` for Python, `cargo-machete` for Rust), then cross-references the unused-dependency list against SCA findings to downrank vulns in code that is never loaded. Use when SCA output (from `osv-scanner`, `snyk-test`, or `npm-pip-maven-audit`) is too noisy to triage and the team needs to separate unreachable CVEs from exploitable ones before sprint planning; sibling cve-exploitability-triage ranks by EPSS/KEV exploitation signal, not code reachability.
79
99%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Per-ecosystem detail for producing unused-deps.txt: config files, flags, exit
codes, and false-positive suppression. Run the tool for your ecosystem, then
extract the unused names for the SCA cross-reference step.
knip is the current recommended tool for unused-dependency detection in JS projects. Per github.com/webpro-nl/knip, it detects unused files, exports, and dependencies including dev-only packages.
npx knip --reporter json > knip-report.json
# Extract unused dependency names for the cross-reference list
npx knip --reporter json | jq -r '.dependencies[].name' > unused-deps.txtdepcheck remains usable for existing setups. Per github.com/depcheck/depcheck, the project was archived in June 2025; the maintainers recommend switching to knip for new setups. For teams still on depcheck:
npx depcheck --json > depcheck-report.json
# Extract unused package names
jq -r '.dependencies[],.devDependencies[]' depcheck-report.json > unused-deps.txtPer github.com/depcheck/depcheck, the
--json flag produces an object with dependencies (unused production deps)
and devDependencies (unused dev deps) as arrays of package-name strings.
Packages in devDependencies that never appear in the production dep tree are
prime candidates for reachable: false annotation on any CVEs they carry.
Suppress known false positives via .depcheckrc:
# .depcheckrc
ignores: ["babel-register", "eslint-*"]
ignore-patterns: ["dist", "coverage"]Dev dependencies in non-production scope are already excluded from many
scanners. Per github.com/depcheck/depcheck,
running npm audit --omit=dev skips devDependencies entirely. Always separate
production and dev unused-dep lists:
# Separate production unused from dev unused
jq -r '.dependencies[]' depcheck-report.json > unused-prod.txt
jq -r '.devDependencies[]' depcheck-report.json > unused-dev.txtPer github.com/jendrikseipp/vulture, vulture detects unused imports, functions, classes, and variables through static analysis. For dependency reachability, unused imports are the direct signal.
pip install vulture
vulture src/ --min-confidence 90 > vulture-report.txtPer github.com/jendrikseipp/vulture,
--min-confidence 90 targets imports specifically (confidence 90% for unused
imports). Lower values include functions and variables, which is noisier for
the dep-CVE cross-reference task.
Extract the unused-import lines:
grep "unused import" vulture-report.txt | sed "s/:.*unused import '\(.*\)'.*/\1/" > unused-imports.txtMap import names back to pip package names using pip show or a manually
maintained import-to-package.txt map, since Python import names often differ
from PyPI package names (e.g. import PIL comes from Pillow).
Configure via pyproject.toml per
github.com/jendrikseipp/vulture:
[tool.vulture]
paths = ["src/"]
min_confidence = 90
exclude = ["tests/", "migrations/"]
ignore_names = ["celery_app", "urlpatterns"]Suppress known false positives (e.g. plugin registrations, dynamic imports) by generating a whitelist:
vulture src/ --make-whitelist > whitelist.py
# Then re-run including the whitelist
vulture src/ whitelist.py --min-confidence 90Per github.com/jendrikseipp/vulture,
exit code 3 means dead code found; 0 means clean.
Per github.com/bnjbvr/cargo-machete,
cargo-machete detects unused [dependencies] in Cargo.toml through fast
static analysis.
cargo install cargo-machete
cargo machetePer github.com/bnjbvr/cargo-machete,
exit code 0 means no unused dependencies found; exit code 1 means at least
one unused dependency was detected; exit code 2 signals a processing error.
For more accurate detection when crates use renamed or feature-gated imports,
use --with-metadata:
cargo machete --with-metadataPer github.com/bnjbvr/cargo-machete,
--with-metadata calls cargo metadata --all-features to resolve final
dependency names, which catches renames that simple text search misses.
Suppress false positives (e.g. proc-macro crates loaded at compile time only)
via Cargo.toml metadata per
github.com/bnjbvr/cargo-machete:
[package.metadata.cargo-machete]
ignored = ["prost", "openssl"]
[package.metadata.cargo-machete.renamed]
rustls-webpki = "webpki"Capture the unused-dep list:
cargo machete 2>&1 | grep "unused dependency" | awk '{print $NF}' > unused-deps.txt