Skip to content

Commit d5e1316

Browse files
authored
docs: add Analog case study and backport findings tables to NestJS and Juice Shop (#199)
* docs: add Analog case study — pnpm v9 monorepo, 3367 packages, 37 findings (closes #197) * docs: add baseline findings table to NestJS case study * docs: add baseline findings table to Juice Shop case study * docs: add Analog case study link to README and website
1 parent f254a1a commit d5e1316

5 files changed

Lines changed: 240 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ CVE Lite CLI complements these tools by serving a practical developer workflow c
216216

217217
- [OWASP Juice Shop](docs/case-studies/owasp-juice-shop.md) — scanning a deliberately vulnerable application with known dependency issues
218218
- [NestJS](docs/case-studies/nestjs.md) — working through a real transitive dependency remediation sequence
219+
- [Analog](docs/case-studies/analog.md) — scanning a modern pnpm v9 Angular monorepo (3,367 packages) with unexpected toolchain vulnerabilities
219220

220221
If you maintain an open-source JavaScript or TypeScript project and want CVE Lite CLI evaluated on it, open an issue and share the repository. Strong candidates may be turned into future public case studies.
221222

docs/case-studies/analog.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Analog Case Study
2+
3+
> Tested with CVE Lite CLI v1.6.0
4+
5+
<p align="center">
6+
<img src="https://raw.githubusercontent.com/analogjs/analog/main/apps/docs-app/static/img/logos/analog-logo.svg" alt="Analog logo" width="260"/>
7+
</p>
8+
9+
## Summary
10+
11+
- **Project:** [Analog](https://github.com/analogjs/analog) — fullstack Angular meta-framework powered by Vite and Nitro, bringing file-based routing, SSR/SSG, and integrated API routes to the Angular ecosystem
12+
- **Revision:** `3b9463ecf9782dc792a049c2e1741060cfdf2dcc`
13+
- **Lockfile:** `pnpm-lock.yaml` (3,367 resolved packages, lockfileVersion 9.0)
14+
- **Baseline findings:** 37 unique vulnerable packages (1 critical · 19 high · 16 medium · 1 low)
15+
- **Direct vs transitive:** 5 direct / 32 transitive
16+
- **Time to first actionable fix command:** under 30 seconds
17+
- **Validated fix command groups generated:** 3
18+
19+
---
20+
21+
## What this case study demonstrates
22+
23+
Analog is a large, actively maintained monorepo. Its lockfile resolves 3,367 packages — more than twice the size of the NestJS and Juice Shop scans — and it uses pnpm's lockfile v9 format, which is the default for any project created with a current pnpm installation.
24+
25+
The direct/transitive split (5 direct, 32 transitive) tells the story immediately: the vast majority of the risk in this codebase is not in packages the project controls. It lives in the toolchain — the documentation generator, the monorepo orchestrator, the CLI, the test runner, and the SSR framework utilities. A developer running `pnpm audit` sees 85 findings with no guidance on which ones they can act on. CVE Lite surfaces 5 directly fixable packages, 3 copy-and-run command groups, and a clear view of which transitive chains are worth investigating and which are structural.
26+
27+
The most instructive chains here are not obvious ones. `@compodoc/compodoc` — the Angular documentation generator — pulls in `handlebars@4.7.8`, the only critical finding in the scan. `@angular/cli` pulls in `@modelcontextprotocol/sdk`, which carries its own high-severity advisory through `hono`. Neither of these paths would surface in a typical developer's mental model of where their security risk lives.
28+
29+
---
30+
31+
## Comparison Note: CVE Lite CLI vs pnpm audit
32+
33+
Both tools were run against the same `pnpm-lock.yaml` on the same machine.
34+
35+
| Metric | pnpm audit | CVE Lite CLI v1.6.0 |
36+
|---|---:|---:|
37+
| Total reported findings | 85 | 37 |
38+
| Critical | 1 | 1 |
39+
| High | 34 | 19 |
40+
| Moderate / Medium | 47 | 16 |
41+
| Low | 3 | 1 |
42+
| Direct vs transitive breakdown || ✓ (5 / 32) |
43+
| Validated fix targets |||
44+
| Breaking change awareness |||
45+
| Parent chain identified for transitive issues |||
46+
| Specific copy-and-run commands |||
47+
48+
**Why CVE Lite reports fewer findings — and why that is not a coverage gap:**
49+
50+
`pnpm audit` counts advisories, not packages. A single vulnerable package with multiple advisories, or one that appears in several dependency paths, contributes multiple entries. CVE Lite counts each unique vulnerable package once. That is why the totals differ: 85 vs 37.
51+
52+
This deduplication is intentional. `lodash` appears three times in this lockfile — `4.17.21` via `@docusaurus/core`, `4.17.23` via `@compodoc/compodoc`, and `lodash-es@4.17.23` via `mermaid`. Each version affects two advisories, each appears in multiple paths. `pnpm audit` counts each advisory-path combination separately. CVE Lite surfaces three distinct package versions, each once, with their parent chains — a more accurate representation of the actual exposure surface.
53+
54+
CVE Lite does not suppress advisories. Every advisory that contributed to a finding is recorded in the `IDs` column of the full table (`--verbose --all`). The deduplication is in the presentation layer, not in the detection layer.
55+
56+
`pnpm audit`'s fix guidance:
57+
58+
```
59+
Run "pnpm audit --fix" to fix 0 of 85 vulnerabilities.
60+
85 vulnerabilities require manual review. See the full report for details.
61+
```
62+
63+
CVE Lite generates:
64+
65+
```bash
66+
# High severity direct fixes
67+
pnpm add @angular/platform-server@21.2.9 defu@6.1.5 happy-dom@20.8.9 vite@8.0.5 @angular/cli@22.0.0-next.0 @vitest/ui@4.1.2 nitropack@2.13.3 nx@22.6.5
68+
69+
# Medium severity direct fix
70+
pnpm add h3@1.15.9
71+
72+
# Medium severity parent upgrades
73+
pnpm add @docusaurus/core@3.9.2-alpha.0 start-server-and-test@3.0.2
74+
```
75+
76+
Each command is a validated non-vulnerable target. `pnpm audit --fix` marks all 85 findings as requiring manual review and offers no commands. CVE Lite identifies 11 packages with confident fix targets, groups them by severity, and separates direct upgrades from parent-chain moves.
77+
78+
---
79+
80+
## Fix Journey
81+
82+
In a modern Angular monorepo, the instinct is to chase the critical finding first. Here, the critical issue — `handlebars@4.7.8` via `@compodoc/compodoc` — has no direct fix command. CVE Lite makes that explicit: the top priority section flags it as a transitive issue requiring a parent-chain upgrade, and the fix plan separates it from the 5 directly actionable packages.
83+
84+
The five direct packages with confident upgrades span two severity levels:
85+
86+
**High severity** (8 packages, one command group): `@angular/platform-server`, `defu`, `happy-dom`, `vite`, `@angular/cli`, `@vitest/ui`, `nitropack`, and `nx`. All have validated non-vulnerable targets. The `@angular/cli` upgrade from `21.2.6` to `22.0.0-next.0` is flagged as a breaking change — it clears the `hono` transitive chain but carries a major version bump.
87+
88+
**Medium severity** (2 groups): `h3@1.15.9` is a clean direct upgrade. `@docusaurus/core` and `start-server-and-test` are parent upgrades that resolve `estree-util-value-to-estree` and `axios` transitive chains respectively.
89+
90+
After those passes, the remaining work belongs to the structural tier: multiple `path-to-regexp` and `picomatch` versions, `serialize-javascript`, `node-forge`, `minimatch`, and `lodash` variants spread across documentation and diagram tooling chains. These are not first-pass candidates — they require tooling upgrades or dependency replacement decisions rather than confident `pnpm add` commands.
91+
92+
---
93+
94+
## Why this matters
95+
96+
Analog is not a neglected project. It has active maintainers, a growing community, and regular releases. A lockfile scan still surfaces 37 vulnerable packages — 32 of them transitive.
97+
98+
That pattern is consistent across every modern JavaScript framework scan: the risk is not in the application code or the framework's runtime dependencies. It is in the toolchain that developers install, trust, and rarely audit — documentation generators, test runners, monorepo orchestrators, and build utilities.
99+
100+
Two chains in this scan are worth naming specifically:
101+
102+
`@compodoc/compodoc``handlebars@4.7.8` (critical). Most Angular developers use `@compodoc` to generate API documentation. It is a devDependency, rarely updated independently, and not a package most teams include in their security review surface. CVE Lite names it as the parent for the only critical finding in the scan.
103+
104+
`@angular/cli``@modelcontextprotocol/sdk``hono` (high). Angular CLI recently incorporated MCP SDK support. That SDK pulls in `hono`, which carries a high-severity advisory. A developer auditing their Angular application would not think to trace security risk through the CLI tool itself. The parent chain makes this visible.
105+
106+
For a team doing a pre-release check, the operationally useful question is not "how many advisories exist?" It is "what do I do right now, and what is structural?" CVE Lite answers that in under 30 seconds: three command groups for the confident first pass, and a clear separation of the transitive remainder.
107+
108+
---
109+
110+
## Scan command
111+
112+
Run from the Analog repository root:
113+
114+
```bash
115+
npx cve-lite-cli . --verbose --all
116+
```
117+
118+
---
119+
120+
## Baseline findings
121+
122+
Full vulnerable package list at scan time:
123+
124+
| Package | Version | Severity | Relationship | Fix hint | Advisory IDs |
125+
|---|---|---|---|---|---|
126+
| handlebars | 4.7.8 | critical | transitive | 4.7.9 | GHSA-q42p-pg8m-cqh6, GHSA-442j-39wm-28r2 |
127+
| @angular/platform-server | 21.2.7 | high | direct | 21.2.9 | GHSA-5pq3-h73f-66hr |
128+
| defu | 6.1.4 | high | direct | 6.1.5 | GHSA-737v-mqg7-c878 |
129+
| flatted | 3.4.1 | high | transitive | 3.4.2 | GHSA-rf6f-7fwh-wjgh |
130+
| happy-dom | 20.8.4 | high | direct | 20.8.8 | GHSA-6q6h-j7hj-3r64, GHSA-w4gp-fjgq-3q4g |
131+
| hono | 4.11.5 | high | transitive | 4.11.7 | GHSA-26pp-8wgv-hjvm, GHSA-458j-xx4x-437… |
132+
| lodash-es | 4.17.23 | high | transitive | 4.18.0 | GHSA-f23m-r3pf-42rh, GHSA-r5fr-rjxr-66jc |
133+
| lodash | 4.17.21 | high | transitive | 4.17.23 | GHSA-f23m-r3pf-42rh, GHSA-r5fr-rjxr-66jc |
134+
| lodash | 4.17.23 | high | transitive | 4.18.0 | GHSA-f23m-r3pf-42rh, GHSA-r5fr-rjxr-66jc |
135+
| minimatch | 3.0.8 | high | transitive | 3.1.3 | GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m2… |
136+
| node-forge | 1.3.3 | high | transitive | 1.4.0 | GHSA-2328-f5f3-gj25, GHSA-5m6q-g25r-mvw… |
137+
| path-to-regexp | 0.1.12 | high | transitive | 0.1.13 | GHSA-37ch-88jc-xwx2 |
138+
| path-to-regexp | 1.8.0 | high | transitive | 0.1.10 | GHSA-9wv6-86v2-598j |
139+
| path-to-regexp | 8.3.0 | high | transitive | 8.4.0 | GHSA-27v5-c462-wpq7, GHSA-j3q9-mxjg-w52f |
140+
| picomatch | 2.3.1 | high | transitive | 2.3.2 | GHSA-3v7f-55p6-f55p, GHSA-c2c7-rcm5-vvqj |
141+
| picomatch | 4.0.3 | high | transitive | 2.3.2 | GHSA-3v7f-55p6-f55p, GHSA-c2c7-rcm5-vvqj |
142+
| serialize-javascript | 6.0.2 | high | transitive | 7.0.3 | GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v |
143+
| svgo | 3.3.2 | high | transitive | 2.8.1 | GHSA-xpqw-6gx7-v673 |
144+
| vite | 8.0.0 | high | direct | 6.4.2 | GHSA-4w7w-66w2-5vf9, GHSA-p9ff-h696-f58… |
145+
| @hono/node-server | 1.19.11 | medium | transitive | 1.19.13 | GHSA-92pp-h63x-v22m |
146+
| ajv | 8.17.1 | medium | transitive | 6.14.0 | GHSA-2g4f-4pwh-qvx6 |
147+
| axios | 1.13.6 | medium | transitive | 0.31.0 | GHSA-3p68-rc4w-qgx5, GHSA-fvcv-3m26-pcqx |
148+
| brace-expansion | 1.1.12 | medium | transitive | 1.1.13 | GHSA-f886-m6hf-6m8v |
149+
| brace-expansion | 2.0.2 | medium | transitive | 1.1.13 | GHSA-f886-m6hf-6m8v |
150+
| brace-expansion | 5.0.4 | medium | transitive | 1.1.13 | GHSA-f886-m6hf-6m8v |
151+
| dompurify | 3.3.3 | medium | transitive | 3.4.0 | GHSA-39q2-94rc-95cp |
152+
| estree-util-value-to-estree | 3.1.1 | medium | transitive | 3.3.3 | GHSA-f7f6-9jq7-3rqj |
153+
| file-type | 20.5.0 | medium | transitive | 21.3.1 | GHSA-5v7r-6r5c-r473, GHSA-j47w-4g3g-c36v |
154+
| follow-redirects | 1.15.11 | medium | transitive | 1.16.0 | GHSA-r4q5-vmmm-2653 |
155+
| h3 | 1.15.6 | medium | direct | 1.15.9 | GHSA-4hxc-9384-m385, GHSA-72gr-qfp7-vwhw |
156+
| mdast-util-to-hast | 13.1.0 | medium | transitive | 13.2.1 | GHSA-4fh9-h7wg-q85m |
157+
| serialize-javascript | 7.0.4 | medium | transitive | 7.0.5 | GHSA-qj8w-gfj5-8c6v |
158+
| smol-toml | 1.6.0 | medium | transitive | 1.6.1 | GHSA-v3rj-xjv7-4jmq |
159+
| yaml | 1.10.2 | medium | transitive | 1.10.3 | GHSA-48c2-rrv3-qjmp |
160+
| yaml | 2.8.2 | medium | transitive | 1.10.3 | GHSA-48c2-rrv3-qjmp |
161+
| @angular/cli | 21.2.6 | low | direct | 22.0.0-next.0 (breaking change) ||
162+
163+
---
164+
165+
## Want your project reviewed?
166+
167+
If you maintain an interesting JavaScript or TypeScript project and want CVE Lite CLI considered for a public case study, open an issue in the [CVE Lite CLI repository](https://github.com/sonukapoor/cve-lite-cli/issues).
168+
169+
Please include:
170+
171+
- the repository link
172+
- why the project would make a useful case study
173+
- whether the dependency graph is publicly reproducible
174+
175+
Not every project will be selected. Preference will go to projects that are publicly useful, technically interesting, and strong examples of realistic dependency remediation workflows.

docs/case-studies/nestjs.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,41 @@ The lower-severity remainder included:
166166

167167
This is a useful stopping point for the public study. The scanner surfaced the one meaningful parent-package move, the move worked once peer-resolution friction was handled, and the remaining work is clearly in the deeper transitive-and-toolchain bucket.
168168

169+
---
170+
171+
## Baseline findings
172+
173+
Full vulnerable package list at scan time:
174+
175+
| Package | Version | Severity | Relationship | Fix hint | Advisory IDs |
176+
|---|---|---|---|---|---|
177+
| form-data | 2.3.3 | critical | transitive | 2.5.4 | GHSA-fjxv-7rqg-78g4 |
178+
| fastify | 5.8.4 | high | direct | 5.8.5 | GHSA-247c-9743-5963 |
179+
| diff | 2.2.3 | high | transitive | 3.5.0 | GHSA-73rr-hh4g-fpgx, GHSA-h6ch-v84p-w6p9 |
180+
| braces | 1.8.5 | high | transitive | 3.0.3 | GHSA-grv7-fg5c-xmjg |
181+
| braces | 2.3.2 | high | transitive | 3.0.3 | GHSA-grv7-fg5c-xmjg |
182+
| lodash.template | 3.6.2 | high | transitive | 4.17.21 | GHSA-35jh-r3h4-6jhm |
183+
| glob | 10.4.5 | high | transitive | 10.5.0 | GHSA-5j98-mcp5-4vw2 |
184+
| serialize-javascript | 6.0.2 | high | transitive | 7.0.3 | GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v |
185+
| tar | 6.2.1 | high | transitive | 7.5.3 | GHSA-34x7-hfp2-rc4v, GHSA-83g3-92jg-28c… |
186+
| postcss | 7.0.39 | medium | transitive | 8.4.31 | GHSA-7fh5-64p2-3v2j |
187+
| brace-expansion | 5.0.4 | medium | transitive | 1.1.13 | GHSA-f886-m6hf-6m8v |
188+
| brace-expansion | 1.1.11 | medium | transitive | 1.1.12 | GHSA-f886-m6hf-6m8v, GHSA-v6h2-p8h4-qcjw |
189+
| brace-expansion | 2.0.2 | medium | transitive | 1.1.13 | GHSA-f886-m6hf-6m8v |
190+
| follow-redirects | 1.15.11 | medium | transitive | 1.16.0 | GHSA-r4q5-vmmm-2653 |
191+
| micromatch | 3.1.10 | medium | transitive | 4.0.8 | GHSA-952p-6rrq-rcjv |
192+
| micromatch | 2.3.11 | medium | transitive | 4.0.8 | GHSA-952p-6rrq-rcjv |
193+
| js-yaml | 3.14.1 | medium | transitive | 3.14.2 | GHSA-mh29-5h37-fv8m |
194+
| js-yaml | 4.1.0 | medium | transitive | 3.14.2 | GHSA-mh29-5h37-fv8m |
195+
| request | 2.88.2 | medium | transitive | 3.0.0 | GHSA-p8p7-x288-28g6 |
196+
| qs | 6.5.3 | medium | transitive | 6.14.1 | GHSA-6rw7-vpxm-498p |
197+
| tough-cookie | 2.5.0 | medium | transitive | 4.1.3 | GHSA-72xf-g2v4-qvf3 |
198+
| yaml | 2.8.2 | medium | transitive | 1.10.3 | GHSA-48c2-rrv3-qjmp |
199+
| @tootallnate/once | 1.1.2 | low | transitive | 3.0.1 | GHSA-vpq2-c234-7xj6 |
200+
| diff | 4.0.2 | low | transitive | 3.5.1 | GHSA-73rr-hh4g-fpgx |
201+
| diff | 7.0.0 | low | transitive | 3.5.1 | GHSA-73rr-hh4g-fpgx |
202+
| qs | 6.14.1 | low | transitive | 6.14.2 | GHSA-w7fw-mjwx-w883 |
203+
169204
## Want your project reviewed?
170205

171206
If you maintain an interesting JavaScript or TypeScript project and want CVE Lite CLI considered for a public case study, open an issue in the [CVE Lite CLI repository](https://github.com/sonukapoor/cve-lite-cli/issues).

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,34 @@ Transitive or structural follow-ups:
150150

151151
This is the part of remediation where a maintainer stops asking "what can I bump today?" and starts asking "which dependencies are worth replacing, and which upgrades deserve broader regression testing?"
152152

153+
---
154+
155+
## Baseline findings
156+
157+
Full vulnerable package list at scan time:
158+
159+
| Package | Version | Severity | Relationship | Fix hint | Advisory IDs |
160+
|---|---|---|---|---|---|
161+
| crypto-js | 3.3.0 | critical | transitive | 4.2.0 | GHSA-xwcq-pm8m-c4vf |
162+
| marsdb | 0.6.11 | critical | direct || GHSA-5mrr-rgp6-x4gr |
163+
| vm2 | 3.9.17 | critical | transitive | 3.9.18 | GHSA-99p7-6v5w-7xg8, GHSA-cchq-frgv-rjh… |
164+
| braces | 2.3.2 | high | transitive | 3.0.3 | GHSA-grv7-fg5c-xmjg |
165+
| jsonwebtoken | 8.5.1 | high | direct | 9.0.0 | GHSA-8cf7-32gw-wr33, GHSA-hjrf-2m68-595… |
166+
| lodash | 4.17.23 | high | transitive | 4.18.0 | GHSA-f23m-r3pf-42rh, GHSA-r5fr-rjxr-66jc |
167+
| minimatch | 3.0.8 | high | transitive | 3.1.3 | GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m2… |
168+
| http-cache-semantics | 3.8.1 | high | transitive | 4.1.1 | GHSA-rc47-6667-2j5j |
169+
| lodash.set | 4.3.2 | high | transitive | 4.17.19 | GHSA-p6mc-m468-83gw |
170+
| minimatch | 9.0.3 | high | transitive | 3.1.3 | GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m2… |
171+
| tar | 4.4.19 | high | transitive | 6.2.1 | GHSA-34x7-hfp2-rc4v, GHSA-83g3-92jg-28c… |
172+
| minimatch | 3.0.5 | high | transitive | 3.1.3 | GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m2… |
173+
| serialize-javascript | 6.0.2 | high | transitive | 7.0.3 | GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v |
174+
| got | 8.3.2 | medium | transitive | 11.8.5 | GHSA-pfrx-2q88-qq97 |
175+
| micromatch | 3.1.10 | medium | transitive | 4.0.8 | GHSA-952p-6rrq-rcjv |
176+
| notevil | 1.3.3 | medium | direct || GHSA-8g4m-cjm2-96wq |
177+
| sanitize-html | 2.17.2 | medium | direct | 2.17.3 | GHSA-9mrh-v2v3-xpfm |
178+
| @tootallnate/once | 2.0.0 | low | transitive | 3.0.1 | GHSA-vpq2-c234-7xj6 |
179+
| messageformat | 2.3.0 | low | transitive | 3.0.0-beta.0 | GHSA-xfqm-j7pc-xrfc |
180+
153181
## Want your project reviewed?
154182

155183
If you maintain an interesting JavaScript or TypeScript project and want CVE Lite CLI considered for a public case study, open an issue in the [CVE Lite CLI repository](https://github.com/sonukapoor/cve-lite-cli/issues).

docs/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ <h3>Real-world case studies</h3>
268268
<p class="link-list">
269269
<a href="https://github.com/sonukapoor/cve-lite-cli/blob/main/docs/case-studies/owasp-juice-shop.md">OWASP Juice Shop</a>
270270
<a href="https://github.com/sonukapoor/cve-lite-cli/blob/main/docs/case-studies/nestjs.md">NestJS</a>
271+
<a href="https://github.com/sonukapoor/cve-lite-cli/blob/main/docs/case-studies/analog.md">Analog</a>
271272
<a href="https://github.com/sonukapoor/cve-lite-cli/blob/main/docs/fix-mode.md">Fix mode guide (--fix)</a>
272273
<a href="https://github.com/sonukapoor/cve-lite-cli/blob/main/docs/how-to-read-verbose-output.md">How to read verbose output</a>
273274
</p>

0 commit comments

Comments
 (0)