Dyad Case Study
Verified baseline scan — CVE Lite CLI v1.22.0 · 2026-06-14
Summary
- Project: Dyad — local AI app builder (Lovable / v0 / Bolt alternative) on Electron + Vite + React
- Revision:
31bae4d687abb94e177f5edebd977ebdd3befa1e - Lockfile: root
package-lock.json(npm, 1,632 resolved packages) - Baseline findings: 51 unique vulnerable packages (4 critical · 29 high · 17 medium · 1 low)
- OSV advisory matches: 128 CVE/advisory entries deduplicated into 51 packages
- Direct vs transitive: 9 direct / 42 transitive
- Validated fix command groups generated: 7
- First-pass coverage: 39 of 51 findings have confident copy-and-run commands
- npm audit (same lockfile): 75 vulnerability entries (5 critical · 47 high · 19 moderate · 4 low)
- Remediation applied in this study: eight command groups applied cumulatively on
examples/dyad/(2026-06-20), rescanned after each pass - Lockfile scope: root
package-lock.jsononly — nested lockfiles underpackages/@dyad-sh/*andtesting/fake-llm-server/are out of scope for this baseline table
What this case study demonstrates
Dyad extends CVE Lite coverage into AI app builder / agent IDE tooling alongside Presenton, Cline, and OpenAI Agents JS. The upstream repo is an Electron + Vite + React stack with MCP integration, Drizzle ORM, Storybook, and Electron Forge — 1,632 resolved packages in the root npm lockfile.
Unlike lean Bun snapshots, Dyad has meaningful direct fix surface: nine direct findings including test stack, MCP SDK, Electron, and Storybook dev tooling.
[email protected] + [email protected] — critical, direct · dev. Test-stack RCE class advisories. CVE Lite generates npm install [email protected] [email protected] with breaking major bumps flagged.
@modelcontextprotocol/[email protected] — high, direct. AI agent tooling dependency. OSV first-fixed hint is 1.24.0, but registry validation marks 1.26.0 as the lowest known non-vulnerable version (1.26.0 ⊘ in the baseline table) — central to Dyad's MCP integration story. Pass 3 installs @modelcontextprotocol/[email protected] alongside other direct upgrades.
[email protected], [email protected], [email protected], [email protected], [email protected], [email protected] — direct findings with copy-and-run npm install or npm update commands.
[email protected] — critical, transitive — ⊘ skipped (no confident lockfile path command in this snapshot).
Four esbuild versions and four minimatch majors illustrate deduplicated package view vs npm audit path expansion.
Comparison Note: CVE Lite CLI vs npm audit
Both tools were run against the same root package-lock.json on the same machine on 2026-06-14.
| Metric | npm audit | CVE Lite CLI v1.22.0 |
|---|---|---|
| Packages parsed / audited | 1,632 | 1,632 |
| Total reported findings | 75 | 51 |
| Critical | 5 | 4 |
| High | 47 | 29 |
| Moderate / Medium | 19 | 17 |
| Low | 4 | 1 |
| Direct vs transitive breakdown | ✗ | ✓ (9 / 42) |
| Deduplicated package view | ✗ | ✓ |
| Validated fix targets | partial | ✓ |
| Copy-and-run command groups | ✗ | ✓ (7 groups) |
| Skipped findings with reason | ✗ | ✓ (12 entries) |
Why the totals differ: npm audit counts 75 vulnerability entries (advisory × path rows). CVE Lite counts 51 unique vulnerable package versions once each. Multiple esbuild, minimatch, tar, and uuid versions each appear as separate unique packages in CVE Lite.
Fix guidance: CVE Lite generates 7 command groups covering 39 findings on first pass — including direct MCP SDK, Electron, and test-stack upgrades plus many within-range npm update refreshes.
Before vs After
Remediation results from applying the scanner's command groups one at a time on examples/dyad/ (npm install + --legacy-peer-deps where peer conflicts blocked default installs), rescanned after each pass (CVE Lite v1.23.0 · 2026-06-20). The 2026-06-14 baseline recorded 51 findings; OSV advisory updates and lockfile resolution shifts produce a 50-finding starting count on this remeasurement date.
| Stage | Findings | Critical | High | Medium | Low | Direct | Transitive | Command groups |
|---|---|---|---|---|---|---|---|---|
| Baseline (verified) | 50 | 3 | 28 | 17 | 2 | 9 | 41 | 8 |
After critical direct fixes (happy-dom, vitest) | 47 | 1 | 28 | 16 | 2 | 7 | 40 | 7 |
After critical within-range refresh (shell-quote) | 46 | 0 | 28 | 16 | 2 | 7 | 39 | 6 |
| After high direct fixes | 32 | 0 | 18 | 12 | 2 | 2 | 30 | 6 |
| After high within-range refreshes | 21 | 0 | 7 | 12 | 2 | 2 | 19 | 6 |
After medium direct fix (uuid) | 20 | 0 | 7 | 11 | 2 | 1 | 19 | 5 |
| After medium within-range refreshes | 18 | 0 | 7 | 9 | 2 | 1 | 17 | 5 |
After low within-range refresh (@vitejs/plugin-react) | 18 | 0 | 7 | 9 | 2 | 1 | 17 | 5 |
After medium parent upgrades (@storybook/addon-essentials, drizzle-kit) | 17 | 0 | 7 | 8 | 2 | 1 | 16 | 5 |
The finding count dropped from 50 to 17 across eight command groups. All four critical findings cleared by pass 2 (happy-dom/vitest direct upgrades + shell-quote refresh). High-severity findings dropped from 28 to 7. The direct package surface shrank from 9 to 1 — the remaining direct row is a skipped target without a confident first-pass command. Command groups dropped from 8 to 5.
Fix Journey
The instinct on 4 critical findings is immediate action. CVE Lite separates direct test-stack fixes (happy-dom, vitest) from transitive next (skipped) and shell-quote (within-range refresh).
Pass 1 — critical direct fixes:
npm install [email protected] [email protected] --legacy-peer-deps
Clears both critical direct test-stack rows. Findings 50 → 47; critical 3 → 1 (transitive next remains).
Pass 2 — critical within-range refresh:
npm update shell-quote --legacy-peer-deps
Clears the critical [email protected] transitive row. Findings 47 → 46; critical 1 → 0.
Pass 3 — high direct fixes:
npm install @modelcontextprotocol/[email protected] [email protected] [email protected] [email protected] [email protected] [email protected] @electron-forge/[email protected] --legacy-peer-deps
Uses registry-validated 1.26.0 for MCP SDK (matching the baseline table fix hint), not the raw OSV hint 1.24.0. Findings 46 → 32; high 28 → 18; direct 7 → 2.
Pass 4 — high within-range refreshes:
npm update @isaacs/brace-expansion @xmldom/xmldom fast-uri lodash minimatch path-to-regexp picomatch seroval tar tar-fs tmp ws --legacy-peer-deps
Largest single drop: findings 32 → 21; high 18 → 7.
Pass 5 — medium direct fix (uuid):
npm install [email protected] --legacy-peer-deps
Findings 21 → 20; direct 2 → 1.
Pass 6 — medium within-range refreshes:
npm update ajv body-parser follow-redirects ip-address qs --legacy-peer-deps
Findings 20 → 18; medium 11 → 9.
Pass 7 — low within-range refresh:
npm update @vitejs/plugin-react --legacy-peer-deps
No finding reduction on this snapshot (18 unchanged) — the remaining low row is on a different path.
Pass 8 — medium parent upgrades:
npm install @storybook/[email protected] [email protected] --legacy-peer-deps
Findings 18 → 17; medium 9 → 8.
After eight passes, 17 findings remain — mostly transitive packages with no confident first-pass command (including skipped next, multiple esbuild/minimatch/rollup rows). Peer dependency friction on @vitest/ui required --legacy-peer-deps for several passes — install-policy friction, not a signal that the upgrade targets were wrong.
Why this matters
Dyad represents local AI app builders with real direct dependency levers — MCP SDK, Electron runtime, Vite, Drizzle ORM — not only transitive framework risk.
CVE Lite's value at 1,632-package scale: 51 unique findings, 9 direct levers, 7 command groups, 39/51 first-pass coverage — versus 75 npm audit rows without remediation structure.
Scan command
Run from the Dyad repository root or from the examples/dyad directory in this repository:
cve-lite . --verbose --all
The example lockfile reflects Dyad at revision 31bae4d687abb94e177f5edebd977ebdd3befa1e. OSV advisory data changes over time — re-scanning may show different counts on the same revision.
Every number in the baseline table comes from a live scan of the committed fixture at examples/dyad/ in the CVE Lite CLI repository. Remediation pass counts were measured on 2026-06-20.
| Field | Value |
|---|---|
| Baseline scan date | 2026-06-14 |
| Remediation measurement date | 2026-06-20 |
| CLI version (baseline) | v1.22.0 |
| CLI version (remediation passes) | v1.23.0 |
| CVE Lite command | node dist/index.js examples/dyad --verbose --all --json |
| npm audit command | npm audit (npm from lockfile, Node.js 24) |
| Advisory source | OSV (https://api.osv.dev) — online mode |
| Lockfile source | examples/dyad/package-lock.json from dyad-sh/dyad@31bae4d |
| Packages parsed (CVE Lite) | 1,632 |
| Unique vulnerable packages (CVE Lite, 2026-06-14) | 51 |
| Vulnerability entries (npm audit) | 75 |
| Fix command groups (CVE Lite) | 7–8 |
| First-pass covered findings (CVE Lite) | 39–41 |
| Skipped findings with reason (CVE Lite) | 12 |
Reproduce CVE Lite locally from the repository root:
npm install
npm run build
node dist/index.js examples/dyad --verbose --all
Reproduce npm audit from the example directory:
cd examples/dyad
npm audit
Both tools were run against the same root package-lock.json on the same machine on 2026-06-14.
Remaining risk after remediation passes
17 findings remain open after the measured eight-pass workflow (down from 50 at the 2026-06-20 remeasurement baseline). The 2026-06-14 baseline table below still lists 51 packages.
- 4 critical:
[email protected],[email protected](direct · dev),[email protected](transitive, ⊘),[email protected](transitive) - 29 high: including direct
@modelcontextprotocol/sdk,electron,drizzle-orm,glob,storybook; fouresbuildversions; fourminimatchversions - 17 medium: including direct
uuid,vite; multiplepostcss,ajv,brace-expansionrows - 1 low:
@tootallnate/[email protected]
Remaining high/medium/low findings have no confident copy-and-run command after all passes (see scan skip reasons) — including skipped [email protected], multiple esbuild/minimatch/rollup versions, and [email protected].
Baseline findings
Full vulnerable package list from the verified scan on 2026-06-14 (revision 31bae4d):
| Package | Version | Severity | Relationship | Fix hint | Advisory IDs |
|---|---|---|---|---|---|
| happy-dom | 17.6.3 | critical | direct · dev | 20.8.9 | CVE-2025-61927, CVE-2026-33943, CVE-2026-34226, GHSA-37j7-fg3j-429f |
| next | 15.5.2 | critical | transitive | 15.5.18 ⊘ | CVE-2026-44575, CVE-2026-45109, CVE-2026-44573, CVE-2026-44572 |
| shell-quote | 1.8.3 | critical | transitive | 1.8.4 | CVE-2026-9277, GHSA-w7jw-789q-3m8p |
| vitest | 3.2.4 | critical | direct · dev | 4.1.0 | CVE-2026-47429, GHSA-5xrq-8626-4rwp |
| @isaacs/brace-expansion | 5.0.0 | high | transitive | 5.0.1 | CVE-2026-25547, GHSA-7h2j-956f-4vf2 |
| @modelcontextprotocol/sdk | 1.18.1 | high | direct | 1.26.0 ⊘ | CVE-2026-25536, CVE-2026-0621, CVE-2025-66414, GHSA-345p-7cg4-v4c7 |
| @xmldom/xmldom | 0.8.11 | high | transitive · dev | 0.8.13 | CVE-2026-41673, CVE-2026-41674, CVE-2026-41672, CVE-2026-34601 |
| axios | 1.14.0 | high | transitive | 1.16.0 | CVE-2026-44494, CVE-2026-44495, CVE-2025-62718, CVE-2026-42044 |
| drizzle-orm | 0.41.0 | high | direct | 0.45.2 | CVE-2026-39356, GHSA-gpj5-g38j-94v9 |
| electron | 40.0.0 | high | direct · dev | 40.8.5 | CVE-2026-34776, CVE-2026-34767, CVE-2026-34774, CVE-2026-34779 |
| esbuild | 0.18.20 | high | transitive · dev | 0.28.1 ⊘ | GHSA-67mh-4wv8-2f99, GHSA-gv7w-rqvm-qjhr |
| esbuild | 0.19.12 | high | transitive · dev | 0.28.1 ⊘ | GHSA-67mh-4wv8-2f99, GHSA-gv7w-rqvm-qjhr |
| esbuild | 0.21.5 | high | transitive | 0.28.1 ⊘ | GHSA-67mh-4wv8-2f99, GHSA-gv7w-rqvm-qjhr |
| esbuild | 0.25.9 | high | transitive | 0.28.1 | GHSA-gv7w-rqvm-qjhr |
| fast-uri | 3.1.0 | high | transitive · dev | 3.1.2 | CVE-2026-6321, CVE-2026-6322, GHSA-q3j6-qgpj-74h6, GHSA-v39h-62p7-jpjc |
| glob | 11.0.3 | high | direct | 11.1.0 | CVE-2025-64756, GHSA-5j98-mcp5-4vw2 |
| lodash | 4.17.21 | high | transitive · dev | 4.18.0 | CVE-2026-2950, CVE-2026-4800, CVE-2025-13465, GHSA-f23m-r3pf-42rh |
| minimatch | 10.0.3 | high | transitive | 10.2.3 | CVE-2026-27904, CVE-2026-26996, CVE-2026-27903, GHSA-23c5-xmqv-rm74 |
| minimatch | 3.1.2 | high | transitive | 3.1.4 ⊘ | CVE-2026-27904, CVE-2026-26996, CVE-2026-27903, GHSA-23c5-xmqv-rm74 |
| minimatch | 5.1.6 | high | transitive · dev | 5.1.8 | CVE-2026-27904, CVE-2026-26996, CVE-2026-27903, GHSA-23c5-xmqv-rm74 |
| minimatch | 9.0.5 | high | transitive | 9.0.7 | CVE-2026-27904, CVE-2026-26996, CVE-2026-27903, GHSA-23c5-xmqv-rm74 |
| path-to-regexp | 8.3.0 | high | transitive | 8.4.0 | CVE-2026-4923, CVE-2026-4926, GHSA-27v5-c462-wpq7, GHSA-j3q9-mxjg-w52f |
| picomatch | 2.3.1 | high | transitive · dev | 2.3.2 | CVE-2026-33672, CVE-2026-33671, GHSA-3v7f-55p6-f55p, GHSA-c2c7-rcm5-vvqj |
| preact | 10.27.1 | high | transitive | 10.27.3 | CVE-2026-22028, GHSA-36hm-qxxp-pg3m |
| rollup | 4.50.1 | high | transitive | 4.59.0 ⊘ | CVE-2026-27606, GHSA-mw96-cpmx-2vgc |
| serialize-javascript | 6.0.2 | high | transitive · dev | 7.0.5 | CVE-2026-34043, GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v |
| seroval | 1.3.2 | high | transitive | 1.4.1 | CVE-2026-24006, CVE-2026-23737, CVE-2026-23957, CVE-2026-23736 |
| storybook | 8.6.15 | high | direct · dev | 8.6.17 | CVE-2026-27148, GHSA-mjf5-7g4m-gx5w |
| tar | 6.2.1 | high | transitive · dev | 7.5.11 | CVE-2026-24842, CVE-2026-26960, CVE-2026-23745, CVE-2026-31802 |
| tar | 7.4.3 | high | transitive | 7.5.11 | CVE-2026-24842, CVE-2026-26960, CVE-2026-23745, CVE-2026-31802 |
| tar-fs | 2.1.3 | high | transitive | 2.1.4 | CVE-2025-59343, GHSA-vj76-c3g6-qr5v |
| tmp | 0.0.33 | high | transitive · dev | 0.2.6 ⊘ | CVE-2025-54798, CVE-2026-44705, GHSA-52f5-9888-hmc6, GHSA-ph9p-34f9-6g65 |
| tmp | 0.2.5 | high | transitive · dev | 0.2.6 | CVE-2026-44705, GHSA-ph9p-34f9-6g65 |
| ajv | 6.12.6 | medium | transitive | 6.14.0 ⊘ | CVE-2025-69873, GHSA-2g4f-4pwh-qvx6 |
| ajv | 8.17.1 | medium | transitive · dev | 8.18.0 | CVE-2025-69873, GHSA-2g4f-4pwh-qvx6 |
| body-parser | 2.2.0 | medium | transitive | 2.2.1 | CVE-2025-13466, GHSA-wqch-xfxh-vrr4 |
| brace-expansion | 1.1.12 | medium | transitive | 1.1.13 | CVE-2026-33750, GHSA-f886-m6hf-6m8v |
| brace-expansion | 2.0.2 | medium | transitive | 2.0.3 | CVE-2026-33750, GHSA-f886-m6hf-6m8v |
| follow-redirects | 1.15.11 | medium | transitive | 1.16.0 | GHSA-r4q5-vmmm-2653 |
| ip-address | 10.1.0 | medium | transitive · dev | 10.1.1 | CVE-2026-42338, GHSA-v2v4-37r5-5v8g |
| js-yaml | 4.1.0 | medium | transitive · dev | 4.1.1 | CVE-2025-64718, GHSA-mh29-5h37-fv8m |
| mdast-util-to-hast | 13.2.0 | medium | transitive | 13.2.1 | CVE-2025-66400, GHSA-4fh9-h7wg-q85m |
| postcss | 8.4.31 | medium | transitive | 8.5.10 ⊘ | CVE-2026-41305, GHSA-qx2v-qp2m-jg93 |
| postcss | 8.5.6 | medium | transitive | 8.5.10 ⊘ | CVE-2026-41305, GHSA-qx2v-qp2m-jg93 |
| qs | 6.14.0 | medium | transitive | 6.15.2 | CVE-2025-15284, CVE-2026-8723, CVE-2026-2391, GHSA-6rw7-vpxm-498p |
| uuid | 11.1.0 | medium | direct | 11.1.1 | CVE-2026-41907, GHSA-w5hq-g745-h8pq |
| uuid | 9.0.1 | medium | transitive · dev | 11.1.1 | CVE-2026-41907, GHSA-w5hq-g745-h8pq |
| vite | 5.4.20 | medium | direct | 6.4.2 ⊘ | CVE-2026-39365, CVE-2025-62522, GHSA-4w7w-66w2-5vf9, GHSA-93m4-6634-74q7 |
| ws | 8.19.0 | medium | transitive · dev | 8.20.1 | CVE-2026-45736, GHSA-58qx-3vcg-4xpx |
| yaml | 2.8.1 | medium | transitive · dev | 2.8.3 | CVE-2026-33532, GHSA-48c2-rrv3-qjmp |
| @tootallnate/once | 2.0.0 | low | transitive · dev | 2.0.1 | CVE-2026-3449, GHSA-vpq2-c234-7xj6 |
Want your project reviewed?
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.
Please include:
- the repository link
- why the project would make a useful case study
- whether the dependency graph is publicly reproducible
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.