Skip to content

Commit 59211ec

Browse files
authored
docs: add usage-aware triage to Juice Shop, NestJS, and Analog case studies (#744)
* docs: add usage-aware triage to Juice Shop, NestJS, and Analog case studies Closes #215 Document --usage and --only-used workflows with measured lockfile vs actionable-subset counts on pinned revisions (CVE Lite v1.25.0 · 2026-06-22). Extend Before vs After tables and Scan command sections for all three studies. * docs: address PR #744 review for usage-aware case studies Clarify Before vs After table mixes triage rows with remediation passes, align Juice Shop revision hash format, and fix v1.6.0 CLI version labels.
1 parent 2528423 commit 59211ec

3 files changed

Lines changed: 158 additions & 13 deletions

File tree

website/docs/case-studies/analog.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Analog Case Study
22

3-
> Tested with CVE Lite CLI v1.6.0
3+
> Verified baseline scan — CVE Lite CLI v1.6.0 · 2026-06-14 (usage-aware remeasurement v1.25.0 · 2026-06-22)
44
55
<p align="center">
66
<img src="https://raw.githubusercontent.com/analogjs/analog/main/apps/docs-app/static/img/logos/analog-logo.svg" alt="Analog logo" width="260"/>
@@ -16,6 +16,7 @@
1616
- **Time to first actionable fix command:** under 30 seconds
1717
- **Validated fix command groups generated:** 3
1818
- **After three remediation passes:** reduced from 37 → 31 findings, direct surface cleared to 0
19+
- **Usage-aware triage (`--only-used`):** **82 → 12** findings on 2026-06-22 remeasurement (70 toolchain/doc packages not statically imported)
1920

2021
---
2122

@@ -76,15 +77,33 @@ pnpm add @docusaurus/core@3.9.2-alpha.0 start-server-and-test@3.0.2
7677

7778
Each command is a validated non-vulnerable stable target. `pnpm audit --fix` marks all 85 findings as requiring manual review and offers no commands. CVE Lite identifies 10 packages with confident fix targets, groups them by severity, and separates direct upgrades from parent-chain moves.
7879

80+
81+
## Usage-aware triage
82+
83+
Analog's 3,367-package lockfile is dominated by documentation generators, Storybook, Nx, and other dev tooling. `--only-used` separates framework runtime imports from that noise.
84+
85+
Measured on revision `3b9463e` with CVE Lite v1.25.0 · 2026-06-22:
86+
87+
| Scan mode | Findings | Critical | High | Medium | Low | Direct | Transitive |
88+
|---|---:|---:|---:|---:|---:|---:|---:|
89+
| Lockfile baseline (`--verbose --all`) | 82 | 4 | 39 | 36 | 3 | 16 | 66 |
90+
| `--only-used` (actionable subset) | 12 | 1 | 6 | 4 | 1 | 12 | 0 |
91+
92+
**82 → 12** — an **85% reduction**. The `--usage` pass marked **70 of 82** findings as not statically imported (`@compodoc/compodoc``handlebars`, `@docusaurus/core` lodash chains, Storybook tooling, etc.). The `--only-used` subset focuses on Angular/Vite runtime packages (`@angular/*`, `vite`, `vitest`, `defu`, `astro`) that application code actually imports.
93+
94+
**Honest limits:** `--usage` uses static import analysis only. It can miss packages loaded dynamically, through build scripts, or via string-based requires. Treat `--only-used` as a triage accelerator — not proof that filtered findings are unreachable at runtime. See [CLI reference](../cli-reference.md).
95+
7996
---
8097

8198
## Before vs After
8299

83-
Remediation results from applying the three command groups documented in this study, measured one group at a time:
100+
The first two rows show the current lockfile baseline and its `--only-used` subset (2026-06-22 remeasurement). The rows below document the remediation passes from the original study (CVE Lite v1.6.0):
84101

85102
| Stage | Findings | Critical | High | Medium | Low | Direct | Transitive | Command groups |
86103
|---|---:|---:|---:|---:|---:|---:|---:|---:|
87-
| Baseline | 37 | 1 | 19 | 16 | 1 | 5 | 32 | 3 |
104+
| Lockfile baseline (2026-06-22 remeasurement) | 82 | 4 | 39 | 36 | 3 | 16 | 66 | 9 |
105+
| `--only-used` filter (same revision) | 12 | 1 | 6 | 4 | 1 | 12 | 0 | 5 |
106+
| Baseline (remediation study, v1.6.0) | 37 | 1 | 19 | 16 | 1 | 5 | 32 | 3 |
88107
| After high severity direct fixes | 33 | 1 | 15 | 16 | 1 | 1 | 32 | 3 |
89108
| After medium severity direct fix | 32 | 1 | 15 | 15 | 1 | 0 | 32 | 2 |
90109
| After medium severity parent upgrades | 31 | 1 | 15 | 14 | 1 | 0 | 31 | 2 |
@@ -125,10 +144,38 @@ For a team doing a pre-release check, the operationally useful question is not "
125144

126145
## Scan command
127146

128-
Run from the Analog repository root:
147+
Run from the Analog repository root (full source clone required for `--usage` / `--only-used`):
129148

130149
```bash
150+
# Full lockfile graph
131151
npx cve-lite-cli . --verbose --all
152+
153+
# Triage: annotate import status per finding
154+
npx cve-lite-cli . --verbose --all --usage
155+
156+
# Actionable subset: statically imported packages only
157+
npx cve-lite-cli . --verbose --all --only-used
158+
```
159+
160+
Usage-aware counts were measured on revision `3b9463e` on 2026-06-22.
161+
162+
| Field | Value |
163+
|---|---|
164+
| Baseline scan date (original study) | 2026-06-14 |
165+
| Usage-aware measurement date | 2026-06-22 |
166+
| CLI version (original study) | v1.6.0 |
167+
| CLI version (usage-aware passes) | v1.25.0 |
168+
| Lockfile findings (2026-06-22) | 82 |
169+
| `--only-used` findings (2026-06-22) | 12 |
170+
171+
Reproduce from a local clone at the pinned revision:
172+
173+
```bash
174+
npm install
175+
npm run build
176+
node dist/index.js examples/analog --verbose --all
177+
node dist/index.js examples/analog --verbose --all --usage
178+
node dist/index.js examples/analog --verbose --all --only-used
132179
```
133180

134181
---

website/docs/case-studies/nestjs.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NestJS Case Study
22

3-
> Tested with CVE Lite CLI v1.6.0
3+
> Verified baseline scan — CVE Lite CLI v1.6.0 · 2026-06-14 (usage-aware remeasurement v1.25.0 · 2026-06-22)
44
55
<p align="center">
66
<img src="https://raw.githubusercontent.com/sonukapoor/cve-lite-cli/main/assets/nestjs-logo.svg" alt="NestJS logo" width="260"/>
@@ -16,6 +16,7 @@
1616
- **Time to first actionable fix command:** under 30 seconds
1717
- **Validated fix commands generated:** 2 (specific versioned targets, not generic `npm audit fix`)
1818
- **After measured pass (remediation study):** reduced from 24 → 21 findings
19+
- **Usage-aware triage (`--only-used`):** **51 → 10** findings on 2026-06-22 remeasurement (41 toolchain/transitive packages not statically imported)
1920

2021
---
2122

@@ -73,15 +74,33 @@ npm install mocha@12.0.0-beta-4
7374

7475
On a project where 25 of 26 findings are transitive, `npm audit fix` is nearly useless. `npm audit fix --force` would attempt to resolve all breakages simultaneously, with no guidance on which upgrades are safe and which introduce API incompatibilities. CVE Lite orders the output — fix the one direct issue first, then the one confident parent upgrade, then reason about the rest.
7576

77+
78+
## Usage-aware triage
79+
80+
NestJS is a full monorepo with source available — most lockfile findings live in test runners, build utilities, and legacy toolchain paths that `--only-used` can filter out.
81+
82+
Measured on revision `cee51af` with CVE Lite v1.25.0 · 2026-06-22:
83+
84+
| Scan mode | Findings | Critical | High | Medium | Low | Direct | Transitive |
85+
|---|---:|---:|---:|---:|---:|---:|---:|
86+
| Lockfile baseline (`--verbose --all`) | 51 | 4 | 18 | 25 | 4 | 8 | 43 |
87+
| `--only-used` (actionable subset) | 10 | 1 | 7 | 2 | 0 | 7 | 3 |
88+
89+
**51 → 10** — an **80% reduction** in finding count. The `--usage` pass marked **41 of 51** findings as not statically imported (gulp toolchain, deprecated `request`/`form-data` chains, test-only paths). The `--only-used` subset surfaces runtime-facing packages like `fastify`, `@grpc/grpc-js`, and multiple `ws` versions still referenced from framework code.
90+
91+
**Honest limits:** `--usage` uses static import analysis only. It can miss packages loaded dynamically, through build scripts, or via string-based requires. Treat `--only-used` as a triage accelerator — not proof that filtered findings are unreachable at runtime. See [CLI reference](../cli-reference.md).
92+
7693
---
7794

7895
## Before vs After
7996

80-
Remediation results from the measured workflow documented in this study (specific revision, v1.5.2 scan):
97+
The first two rows show the current lockfile baseline and its `--only-used` subset (2026-06-22 remeasurement). The rows below document the remediation passes from the original study (CVE Lite v1.6.0):
8198

8299
| Stage | Findings | Critical | High | Medium | Low | Direct | Transitive | Command groups |
83100
|---|---:|---:|---:|---:|---:|---:|---:|---:|
84-
| Baseline | 24 | 0 | 1 | 4 | 19 | 0 | 24 | 1 |
101+
| Lockfile baseline (2026-06-22 remeasurement) | 51 | 4 | 18 | 25 | 4 | 8 | 43 | 9 |
102+
| `--only-used` filter (same revision) | 10 | 1 | 7 | 2 | 0 | 7 | 3 | 3 |
103+
| Baseline (remediation study, v1.6.0) | 24 | 0 | 1 | 4 | 19 | 0 | 24 | 1 |
85104
| After measured pass | 21 | 0 | 1 | 3 | 17 | 0 | 21 | 0 |
86105

87106
The finding count dropped from 24 to 21. The generated command surface dropped from 1 group to 0 — meaning the scanner moved the repository into the deeper transitive-only category where the remaining work belongs to toolchain and parent-chain decisions rather than confident first-pass installs.
@@ -128,14 +147,42 @@ That distinction matters especially in CI. A flat advisory count of 36 triggers
128147

129148
## Scan command
130149

131-
Run from the NestJS root:
150+
Run from the NestJS repository root (full source clone required for `--usage` / `--only-used`):
132151

133152
```bash
153+
# Full lockfile graph
134154
npx cve-lite-cli . --verbose --all
155+
156+
# Triage: annotate import status per finding
157+
npx cve-lite-cli . --verbose --all --usage
158+
159+
# Actionable subset: statically imported packages only
160+
npx cve-lite-cli . --verbose --all --only-used
135161
```
136162

137163
The remediation walkthrough was performed locally against that revision. Dependency changes were applied during the exercise, but they were not committed in the NestJS repository.
138164

165+
Usage-aware counts were measured on revision `cee51af` on 2026-06-22.
166+
167+
| Field | Value |
168+
|---|---|
169+
| Baseline scan date (original study) | 2026-06-14 |
170+
| Usage-aware measurement date | 2026-06-22 |
171+
| CLI version (original study) | v1.6.0 |
172+
| CLI version (usage-aware passes) | v1.25.0 |
173+
| Lockfile findings (2026-06-22) | 51 |
174+
| `--only-used` findings (2026-06-22) | 10 |
175+
176+
Reproduce from a local clone at the pinned revision:
177+
178+
```bash
179+
npm install
180+
npm run build
181+
node dist/index.js examples/nest --verbose --all
182+
node dist/index.js examples/nest --verbose --all --usage
183+
node dist/index.js examples/nest --verbose --all --only-used
184+
```
185+
139186
## Remaining risk after the measured pass
140187

141188
The post-pass lockfile still contained `21` findings:

website/docs/case-studies/owasp-juice-shop.md

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OWASP Juice Shop Case Study
22

3-
> Tested with CVE Lite CLI v1.6.0
3+
> Verified baseline scan — CVE Lite CLI v1.6.0 · 2026-06-14 (usage-aware remeasurement v1.25.0 · 2026-06-22)
44
55
<p align="center">
66
<img src="https://raw.githubusercontent.com/juice-shop/juice-shop/master/frontend/src/assets/public/images/JuiceShop_Logo_400px.png" alt="OWASP Juice Shop logo" width="260"/>
@@ -16,6 +16,7 @@
1616
- **Time to first actionable fix command:** under 30 seconds
1717
- **Validated fix commands generated:** 2 (specific versioned targets, not generic `npm audit fix`)
1818
- **After two remediation passes:** reduced from 39 → 18 findings across an earlier study revision
19+
- **Usage-aware triage (`--only-used`):** issue #215 validated **19 → 5** actionable findings at feature launch; 2026-06-22 remeasurement shows **3 → 3** (all remaining lockfile findings are statically imported)
1920

2021
---
2122

@@ -75,15 +76,35 @@ Each command is a validated non-vulnerable target. `npm audit fix --force` is a
7576

7677
`npm audit` does not distinguish direct from transitive findings. On a project with 15 transitive issues, that means a developer sees 55 entries without knowing which ones they can act on immediately and which require parent-chain decisions.
7778

79+
80+
## Usage-aware triage
81+
82+
Juice Shop ships full application source — ideal for `--usage` / `--only-used` triage. The lockfile still lists toolchain and transitive packages that never appear in runtime code paths.
83+
84+
Measured on revision `7ae7184dbf84baae9ee1d85be39f793b777ae996` with CVE Lite v1.25.0 · 2026-06-22:
85+
86+
| Scan mode | Findings | Critical | High | Medium | Low | Direct | Transitive |
87+
|---|---:|---:|---:|---:|---:|---:|---:|
88+
| Lockfile baseline (`--verbose --all`) | 3 | 1 | 2 | 0 | 0 | 3 | 0 |
89+
| `--only-used` (actionable subset) | 3 | 1 | 2 | 0 | 0 | 3 | 0 |
90+
91+
At feature launch ([#215](https://github.com/OWASP/cve-lite-cli/issues/215)), the same revision produced **19 lockfile findings → 5 with `--only-used`** — the headline noise-reduction example. OSV advisory updates since the original v1.6.0 study reduced the lockfile baseline to **3** packages on this remeasurement date; all three are statically imported (`jsonwebtoken`, `express-jwt`, `sanitize-html` paths in routes and lib code), so the filter does not shrink the count further today.
92+
93+
For day-to-day triage on a larger advisory surface, run the lockfile scan first, then `--only-used` to separate application-reachable packages from dev/toolchain noise.
94+
95+
**Honest limits:** `--usage` uses static import analysis only. It can miss packages loaded dynamically, through build scripts, or via string-based requires. Treat `--only-used` as a triage accelerator — not proof that filtered findings are unreachable at runtime. See [CLI reference](../cli-reference.md).
96+
7897
---
7998

8099
## Before vs After
81100

82-
Remediation results from the measured workflow documented in this study (earlier revision, v1.5.2):
101+
The first two rows show the current lockfile baseline and its `--only-used` subset (2026-06-22 remeasurement). The rows below document the remediation passes from the original study (CVE Lite v1.6.0):
83102

84103
| Stage | Findings | Critical | High | Medium | Low | Direct | Transitive | Command groups |
85104
|---|---:|---:|---:|---:|---:|---:|---:|---:|
86-
| Baseline | 39 | 3 | 1 | 11 | 23 | 10 | 29 | 6 |
105+
| Lockfile baseline (2026-06-22 remeasurement) | 3 | 1 | 2 | 0 | 0 | 3 | 0 | 0 |
106+
| `--only-used` filter (same revision) | 3 | 1 | 2 | 0 | 0 | 3 | 0 | 0 |
107+
| Baseline (remediation study, v1.6.0) | 39 | 3 | 1 | 11 | 23 | 10 | 29 | 6 |
87108
| After first direct pass | 27 | 1 | 0 | 10 | 16 | 4 | 23 | 3 |
88109
| After second pass | 18 | 1 | 0 | 5 | 12 | 3 | 15 | 1 |
89110

@@ -115,12 +136,42 @@ CVE Lite's output answers the operational question: what do I do right now, and
115136

116137
---
117138

118-
## Project context
139+
## Scan command
119140

120-
Baseline scan command from the Juice Shop root:
141+
Run from the Juice Shop repository root (full source clone required for `--usage` / `--only-used`):
121142

122143
```bash
144+
# Full lockfile graph
123145
npx cve-lite-cli . --verbose --all
146+
147+
# Triage: annotate import status per finding
148+
npx cve-lite-cli . --verbose --all --usage
149+
150+
# Actionable subset: statically imported packages only
151+
npx cve-lite-cli . --verbose --all --only-used
152+
```
153+
154+
Every number in the usage-aware table comes from live scans of revision `7ae7184dbf84baae9ee1d85be39f793b777ae996` on 2026-06-22.
155+
156+
| Field | Value |
157+
|---|---|
158+
| Baseline scan date (original study) | 2026-06-14 |
159+
| Usage-aware measurement date | 2026-06-22 |
160+
| CLI version (original study) | v1.6.0 |
161+
| CLI version (usage-aware passes) | v1.25.0 |
162+
| Revision | `7ae7184dbf84baae9ee1d85be39f793b777ae996` |
163+
| Lockfile findings (2026-06-22) | 3 |
164+
| `--only-used` findings (2026-06-22) | 3 |
165+
| `--only-used` at feature launch ([#215](https://github.com/OWASP/cve-lite-cli/issues/215)) | 5 (from 19 lockfile) |
166+
167+
Reproduce from a local clone at the pinned revision:
168+
169+
```bash
170+
npm install
171+
npm run build
172+
node dist/index.js examples/juice-shop --verbose --all
173+
node dist/index.js examples/juice-shop --verbose --all --usage
174+
node dist/index.js examples/juice-shop --verbose --all --only-used
124175
```
125176

126177
One practical detail mattered during this run: Juice Shop has `package-lock=false` in `.npmrc`. That means a normal `npm install` can update `package.json` and local installs without updating the lockfile snapshot the scanner reads. To keep the case study honest, the lockfile was refreshed after each install batch with:

0 commit comments

Comments
 (0)