|
1 | 1 | # OWASP Juice Shop Case Study |
2 | 2 |
|
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) |
4 | 4 |
|
5 | 5 | <p align="center"> |
6 | 6 | <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 | 16 | - **Time to first actionable fix command:** under 30 seconds |
17 | 17 | - **Validated fix commands generated:** 2 (specific versioned targets, not generic `npm audit fix`) |
18 | 18 | - **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) |
19 | 20 |
|
20 | 21 | --- |
21 | 22 |
|
@@ -75,15 +76,35 @@ Each command is a validated non-vulnerable target. `npm audit fix --force` is a |
75 | 76 |
|
76 | 77 | `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. |
77 | 78 |
|
| 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 | + |
78 | 97 | --- |
79 | 98 |
|
80 | 99 | ## Before vs After |
81 | 100 |
|
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): |
83 | 102 |
|
84 | 103 | | Stage | Findings | Critical | High | Medium | Low | Direct | Transitive | Command groups | |
85 | 104 | |---|---:|---:|---:|---:|---:|---:|---:|---:| |
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 | |
87 | 108 | | After first direct pass | 27 | 1 | 0 | 10 | 16 | 4 | 23 | 3 | |
88 | 109 | | After second pass | 18 | 1 | 0 | 5 | 12 | 3 | 15 | 1 | |
89 | 110 |
|
@@ -115,12 +136,42 @@ CVE Lite's output answers the operational question: what do I do right now, and |
115 | 136 |
|
116 | 137 | --- |
117 | 138 |
|
118 | | -## Project context |
| 139 | +## Scan command |
119 | 140 |
|
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`): |
121 | 142 |
|
122 | 143 | ```bash |
| 144 | +# Full lockfile graph |
123 | 145 | 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 |
124 | 175 | ``` |
125 | 176 |
|
126 | 177 | 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