From 0c048c422ccad313a4fb884e848f90e1a5a06cbd Mon Sep 17 00:00:00 2001 From: Sonu Kapoor Date: Sat, 25 Jul 2026 11:45:36 -0400 Subject: [PATCH] docs: add maintenance-risk (DM001) documentation section Add a maintenance-risk docs section mirroring override-hygiene: a concept page explaining constraint drag and deprecated-dependency detection and how --check-maintenance fits alongside CVE and override findings, plus a DM001 rule page. Wire both into the sidebar after Override Hygiene and cross-link the two sections. Example output uses markdown tables rather than ASCII art. Closes #855 --- website/docs/maintenance-risk/dm001.md | 59 ++++++++++++++++ website/docs/maintenance-risk/index.md | 96 ++++++++++++++++++++++++++ website/docs/override-hygiene/index.md | 6 ++ website/sidebars.ts | 9 +++ 4 files changed, 170 insertions(+) create mode 100644 website/docs/maintenance-risk/dm001.md create mode 100644 website/docs/maintenance-risk/index.md diff --git a/website/docs/maintenance-risk/dm001.md b/website/docs/maintenance-risk/dm001.md new file mode 100644 index 00000000..7ea4a676 --- /dev/null +++ b/website/docs/maintenance-risk/dm001.md @@ -0,0 +1,59 @@ +--- +title: "DM001: Maintenance Risk" +description: A direct dependency that blocks a transitive CVE fix behind a major-version upgrade, or that is deprecated on npm. +--- + +# DM001: Maintenance Risk + +**Severity:** high  ยท  **Auto-fix:** no (remediation is a manual major-version upgrade) + +DM001 flags a direct dependency that is a maintenance liability for your security posture. It fires on either of two signals: + +- **Constraint drag** - the direct dependency pins a transitive dependency below the version that fixes a known CVE, and clearing the block requires a **major-version** upgrade of the direct dependency (a breaking change). +- **Deprecated on npm** - the direct dependency's latest published version is marked deprecated on the npm registry, so no fix is coming through a normal update. + +The finding is reported against the **direct (parent) dependency** that is causing the problem, not the transitive package the CVE is in - because the parent is what you have to change. + +--- + +## Example: constraint drag + +Your scan reports a CVE in `js-yaml`, fixed in `4.0.0`. But you do not depend on `js-yaml` directly - `gray-matter@2.1.0` does, and its version range only allows `js-yaml` below `4.0.0`. The transitive fix is unreachable until you upgrade `gray-matter` itself, and the next `gray-matter` that permits the fix is a major version (`5.0.0`). + +A version-matching scanner tells you "upgrade js-yaml." DM001 tells you the truth: `gray-matter` is dragging `js-yaml` below its fix, and only a major `gray-matter` upgrade resolves it. + +--- + +## Output + +Maintenance findings are grouped by severity under a `๐Ÿ”ง Maintenance Risk` heading. A constraint-drag finding renders like this: + +| Rule | Package | Details | +|---|---|---| +| DM001 | `gray-matter@2.1.0` | Drags `js-yaml@3.13.1` below fix `4.0.0` - upgrade to `5.0.0` | + +When the blocking dependency is also deprecated on npm, a second detail line appears in the same finding: + +| Rule | Package | Details | +|---|---|---| +| DM001 | `gray-matter@2.1.0` | npm deprecated: This package is no longer maintained | + +--- + +## Fix + +There is no automatic fix. The remediation is a real dependency decision: + +```bash +# Upgrade the blocking direct dependency to the version that permits the fix. +# This is a MAJOR version bump - review its changelog for breaking changes first. +npm install gray-matter@5.0.0 +``` + +Then rescan to confirm the transitive CVE is resolved. If the blocking dependency is deprecated, plan a migration to a maintained alternative - a deprecated dependency will not receive future security fixes. + +--- + +## Offline behavior + +The constraint-drag signal is computed entirely from the resolved dependency graph, so it works `--offline`. The deprecated-on-npm signal requires a registry lookup and is skipped in offline mode; the drag finding is still reported without it. diff --git a/website/docs/maintenance-risk/index.md b/website/docs/maintenance-risk/index.md new file mode 100644 index 00000000..f8f7babd --- /dev/null +++ b/website/docs/maintenance-risk/index.md @@ -0,0 +1,96 @@ +--- +title: Maintenance Risk Detection +description: Find direct dependencies that block a transitive CVE fix behind a major-version upgrade, or that are deprecated on npm. +--- + +# Maintenance Risk Detection + +A CVE scanner tells you a transitive package is vulnerable. It does not tell you *why you cannot fix it*. Often the answer is one of your own direct dependencies: it pins the vulnerable package below its fixed version, and the only way out is a major-version upgrade of that direct dependency - a breaking change the scanner never mentions. The finding looks fixable; in practice it is stuck. + +This is maintenance risk, and it is invisible to tools that only match versions against advisories. A package can be perfectly up to date on its own line and still hold your whole tree hostage. + +`cve-lite . --check-maintenance` looks for this pattern directly. It flags the direct dependencies that are blocking a CVE fix (constraint drag) and the direct dependencies that are deprecated on npm, so you see the maintenance decisions hiding behind your vulnerability list. + +--- + +## Running the check + +`--check-maintenance` runs alongside a regular CVE scan in one pass: + +```bash +cve-lite . --check-maintenance # CVE scan + maintenance risk +cve-lite . --check-maintenance --json # combined JSON output +cve-lite . --check-maintenance --fail-on high # fail CI on a high finding +cve-lite . --check-maintenance --offline # drag detection only (no deprecated check) +``` + +Maintenance findings render in the terminal, in `--verbose`, in the JSON output, and in the HTML report (`--report`), and they count toward `--fail-on`. + +There is no separate subcommand and no `--fix` for maintenance risk: unlike an override, the remediation is a real, potentially breaking, major-version upgrade of a direct dependency, so it is surfaced for a human to decide rather than applied automatically. + +--- + +## The rules + +| Rule | Name | Severity | What it detects | +|---|---|---|---| +| [DM001](./dm001.md) | Maintenance risk | high | A direct dependency that pins a transitive dependency below its CVE fix (needs a major-version parent upgrade), or that is deprecated on npm | + +The maintenance-risk family is designed to grow: staleness (last-publish age) and repository-archive detection are planned as additional signals. + +--- + +## Why CVE scanners miss this + +```mermaid +flowchart TD + A["CVE found in transitive dep"] --> B["Scanner reports: upgrade the transitive dep"] + B --> C["But a direct dep pins it below the fix"] + C --> D["The only real fix is a MAJOR upgrade of the direct dep"] + D --> E1["Major upgrade is breaking - team defers it"] + D --> E2["Scanner never mentions the direct dep at all"] + E1 --> F["Vulnerability sits unfixed, looking 'fixable'"] + E2 --> F + F --> G["Or worse: the blocking direct dep is deprecated - no fix is coming"] + style A fill:#1e3a5f,color:#93c5fd,stroke:#3b82f6,padding:12px + style B fill:#1e3a5f,color:#93c5fd,stroke:#3b82f6,padding:12px + style C fill:#7c2d12,color:#fdba74,stroke:#f97316,padding:12px + style D fill:#7c2d12,color:#fdba74,stroke:#f97316,padding:12px + style E1 fill:#7c2d12,color:#fdba74,stroke:#f97316,padding:12px + style E2 fill:#7c2d12,color:#fdba74,stroke:#f97316,padding:12px + style F fill:#7f1d1d,color:#fca5a5,stroke:#ef4444,padding:12px + style G fill:#7f1d1d,color:#fca5a5,stroke:#ef4444,padding:12px +``` + +A version-matching scanner sees the vulnerable transitive package and stops. It does not walk back up the tree to identify which direct dependency is holding the fix hostage, and it has no concept of a package being deprecated or abandoned. `--check-maintenance` adds that upstream view. + +--- + +## How this fits alongside CVE and override findings + +CVE Lite CLI surfaces three complementary kinds of risk in one scan: + +- **CVE findings** - a package version matches a known vulnerability advisory. +- **[Override hygiene](../override-hygiene/index.md)** (`--check-overrides`) - a manual `overrides`/`resolutions` patch is stale, misplaced, or failing to take effect. +- **Maintenance risk** (`--check-maintenance`) - a direct dependency is blocking a CVE fix behind a major-version wall, or is deprecated on npm. + +The three answer different questions - *what is vulnerable*, *did my patch work*, and *why can't I fix it* - and can be combined: + +```bash +cve-lite . --check-overrides --check-maintenance --fail-on high +``` + +--- + +## How this compares to other tools + +Most dependency scanners match installed versions against advisory ranges and report what is vulnerable. They do not model the relationship between a direct dependency's version constraint and a transitive fix, so they never surface the maintenance decision that is actually blocking remediation. + +| Capability | --check-maintenance | npm audit | OSV-Scanner | Snyk CLI | Socket CLI | +|---|---|---|---|---|---| +| Flag the direct dep blocking a transitive CVE fix (DM001) | โœ… | โŒ | โŒ | โŒ | โŒ | +| Distinguish a within-range fix from a major-upgrade wall | โœ… | โŒ | โŒ | โŒ | โŒ | +| Flag a deprecated direct dependency | โœ… | โŒ | โŒ | โŒ | โŒ | +| Count maintenance risk toward a CI gate (`--fail-on`) | โœ… | โŒ | โŒ | โŒ | โŒ | + +Maintenance risk detection is part of what makes CVE Lite CLI, an OWASP Lab Project, more than a version matcher: it explains not just what is vulnerable, but what is standing between you and the fix. diff --git a/website/docs/override-hygiene/index.md b/website/docs/override-hygiene/index.md index 3fc76111..887167ce 100644 --- a/website/docs/override-hygiene/index.md +++ b/website/docs/override-hygiene/index.md @@ -153,3 +153,9 @@ Most dependency security tools read `package.json` statically and stop there. Th | Cross-reference override against parent deps | โœ… | โŒ | โŒ | โŒ | โŒ | | Auto-fix with RFC 6902 patches | โœ… | โŒ | โŒ | โŒ | โŒ | | Works offline | โœ… | โŒ | โœ… | โŒ | โŒ | + +--- + +## Related + +Override hygiene answers *did my manual patch work*. Its sibling, [Maintenance Risk Detection](../maintenance-risk/index.md) (`--check-maintenance`), answers *why can't I fix this at all* - flagging a direct dependency that blocks a transitive CVE fix behind a major-version upgrade, or that is deprecated on npm. Run both alongside a scan with `cve-lite . --check-overrides --check-maintenance`. diff --git a/website/sidebars.ts b/website/sidebars.ts index 241ea477..90477718 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -52,6 +52,15 @@ const sidebars: SidebarsConfig = { 'override-hygiene/pd002', ], }, + { + type: 'category', + label: 'Maintenance Risk', + link: { type: 'doc', id: 'maintenance-risk/index' }, + collapsed: true, + items: [ + 'maintenance-risk/dm001', + ], + }, 'ai-assistant-integration', 'nx-workspaces', 'sarif',