Unused production dependencies are pure supply chain liability: they represent packages that must be audited for CVEs, monitored for deprecation, and maintained through version upgrades — all while providing zero functionality. CWE-1357 applies directly: relying on more third-party components than your software requires increases the attack surface proportionally. SSDF PW.4 requires that the software composition be intentional and minimal. AI coding tools are the primary source of unused dependency accumulation — they install a package to explore an approach, then implement a different solution, but never run npm uninstall. The result is a package.json that describes a project that never existed.
Info because unused dependencies do not themselves contain vulnerabilities in the running application, but they are pure supply chain overhead that increases audit burden without contributing any functionality.
Identify and remove unused dependencies:
npx depcheck
Review the output carefully — depcheck reports false positives for packages loaded via dynamic imports, config files, or peer dependency mechanisms. For each confirmed unused package:
npm uninstall unused-package
Commit the updated package.json and lock file together. Add depcheck to a monthly engineering review cycle to prevent accumulation between audits.
ID: dependency-supply-chain.optimization.no-unused-deps
Severity: info
What to look for: Examine package.json dependencies and check for packages that appear to have no import references in the source code. Run or simulate npx depcheck mentally: for each production dependency, verify at least one import or require of that package name exists in a .ts, .tsx, .js, or .jsx file. Common patterns of unused packages left by AI tools: packages installed to evaluate an approach then abandoned, packages replaced by an equivalent but the original was never removed, packages needed only in scripts but listed under dependencies. Count all instances found and enumerate each.
Pass criteria: All production dependencies have at least one usage reference in source code, or are used indirectly in a way that doesn't require explicit imports. Indirect usage patterns that count as "used": (1) PostCSS plugins, Babel transforms, and Tailwind plugins referenced in config files (postcss.config.mjs, tailwind.config.ts); (2) ESLint configs and plugins referenced in eslint.config.mjs or .eslintrc; (3) Packages imported transitively through barrel files or wrapper modules (e.g., @supabase/ssr imported in src/lib/supabase/server.ts counts as used even if no other file imports it directly); (4) Next.js plugins configured in next.config.ts; (5) CLI tools referenced in package.json scripts. At least 1 implementation must be confirmed.
Fail criteria: One or more production dependencies appear to have no usage references in source code, config files, or package.json scripts, and are not framework plugins or transitive dependencies of used packages.
Skip (N/A) when: No package.json detected.
Detail on fail: "No import found for 'some-lib' in production dependencies — this may be unused. Run 'npx depcheck' to verify." List up to 5 packages.
Remediation: Unused packages increase attack surface without providing benefit. AI tools often install packages during exploration and forget to remove them.
To identify unused dependencies:
npx depcheck
Review the output — depcheck can have false positives for:
After confirming a package is unused:
npm uninstall unused-package