Skip to content

feat: PD001 and PD002 phantom dependency detection for overrides#826

Open
sonukapoor wants to merge 17 commits into
mainfrom
feature/issue-731-phantom-dependencies
Open

feat: PD001 and PD002 phantom dependency detection for overrides#826
sonukapoor wants to merge 17 commits into
mainfrom
feature/issue-731-phantom-dependencies

Conversation

@sonukapoor

Copy link
Copy Markdown
Collaborator

Adds two new override hygiene rules that detect phantom dependency imports - packages your source code imports that are not declared as a direct dependency.

What's new

PD001 - Override-only phantom (high): fires when source code imports a package that is only present because an override pin keeps it in the resolved graph. In pnpm strict mode (default on Vercel), this causes a silent deploy failure - the import works locally via hoisting but breaks in production.

PD002 - Transitive-only phantom (medium): fires when source code imports a package that is only present as a transitive dependency of a parent. If the parent drops or changes the dep, the import breaks silently on the next install with no lockfile conflict warning.

Both rules scan source files for import, require, and export statements, cross-reference the resolved lockfile and declared dependencies, and report the specific files containing the phantom import.

Also in this PR

  • OA009 safety guard: suppresses the "remove stale floor" suggestion when the override is the only thing keeping a phantom-imported package available
  • overrides --json now writes to a file (cve-lite-overrides-<ts>.json) instead of stdout, consistent with the main scan path
  • examples/all-scenarios/ fixture: single project that triggers all nine auto-detectable rules in one scan (OA001x2, OA002, OA003, OA004, OA005, OA009, PD001, PD002)
  • Fix-all tip: when 2+ rules are auto-fixable, a tip line appears after the findings suggesting cve-lite overrides --fix to apply everything in one shot
  • PD001 and PD002 rule pages in the docs, sidebar entries, SARIF registration, and README/override-hygiene index updated to reflect 11 rules

Closes #731

sonukapoor added 17 commits July 9, 2026 09:00
…ide hygiene rules

Adds examples/all-scenarios - a single static fixture that triggers all nine
override hygiene findings in one scan (OA001x2, OA002, OA003, OA004, OA005,
OA009, PD001, PD002). OA006/OA007/OA008 are excluded since they require
live node_modules or network registry access.

Includes minimal node_modules stubs for OA004 and OA009 (which read installed
package manifests on disk). Extends .gitignore to commit those stubs.
…xable

When multiple rules have auto-fix support, the hint block now leads with
`cve-lite <path> overrides --fix` so users can fix everything in one shot.
Per-rule commands follow for surgical control. All hints are consolidated
into a single block after all severity tables instead of appearing after
each table separately.
… fixable

Per-rule `--fix --rule XYZ` commands now appear below each severity box,
matching the pattern verbose mode uses for main scan fix commands. When
2+ rules have auto-fix support, a tip line is added after the last box:

  Tip: run `cve-lite <path> overrides --fix` to apply all auto-fixable
  fixes in one shot.

The tip appears in both the standalone overrides command and verbose mode
with --check-overrides, since both share the same renderer. Single-rule
scans continue to show only the per-rule command with no tip.
…dalone overrides

renderOverrideFindings was prepending its own leading blank line, which
collided with the blank line printBanner already emits. Moved ownership
of the leading blank to callers: removed lines.push("") from the renderer
and added "\n" in the two inline --check-overrides call sites in index.ts.
The standalone overrides command now shows a single blank line, and
verbose mode retains the gap before the Override Hygiene section.
…rides distinction

README: updates nine to eleven rules, adds PD001/PD002 rows to the table,
and adds an explicit paragraph explaining that the overrides subcommand is
hygiene-only (no CVE scan, faster, offline-capable) while --check-overrides
runs both in one pass. Also fixes the inline comment in the quick-start
examples.

override-hygiene/index.md: rewrites the --check-overrides/subcommand note
to explicitly state that --check-overrides runs the full CVE scan alongside
hygiene, and that the overrides subcommand skips the CVE scan entirely.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: detect phantom dependencies - packages imported but not declared (PD001/PD002)

1 participant