deps: patch high-severity dependency vulnerabilities - #147
Conversation
There was a problem hiding this comment.
Important
The nanoid half of this lands correctly, but the sharp half is inert — a fresh install of this lockfile still puts every real sharp consumer on the vulnerable 0.34.5, and 0.35.3 ends up with zero consumers.
Reviewed changes — a two-package security bump plus the regenerated Bun lockfile, checked against the published advisories, against this repo's Node/runtime targets, and against what bun install actually materializes on disk.
sharp0.34.5 → 0.35.3 inapps/docs— targets GHSA-f88m-g3jw-g9cj (High, CVSS 7.0), whose root cause is the bundledlibvipsbinaries rather than sharp's JS.nanoid5.1.6 → 5.1.16 inpackages/utils— targets GHSA-28wg-ghj8-5hjv / CVE-2026-67214 (High, CVSS 8.2). 5.1.16 is exactly the minimum patched version. Worth noting the older CVE-2024-55565 (fixed in 5.0.9) does not apply to 5.1.6, so this newer advisory is the real justification.bun.lockregeneration — the large majority of the +190 lines are new nested entries that pin the OLDsharp@0.34.5andnanoid@5.1.6for transitive consumers.
Both target versions are the right choices, and compatibility is clean: sharp 0.35.0 requires Node >= 20.9.0, this repo targets Node 24 everywhere (root engines, .nvmrc, all three workflows), no source file imports sharp directly, and the new @types/node optional peer plus the freebsd/webcontainers wasm optional deps are platform-gated and inert on Linux CI.
⚠️ Nothing in the stated verification can detect that the vulnerable code is still installed
bun run check, bun run check:monorepo, bun test and bun run build --filter=docs all pass while sharp@0.34.5 and its @img/sharp-libvips-linux-x64@1.2.4 binary remain in the tree. That is exactly how a dependency-patch PR can look green and still ship the vulnerability, and it will happen again on the next advisory unless something asserts on the resolved graph rather than on the declared version.
This also raises a scope question only you can settle: is the goal to remove the vulnerable code from the installed tree, or to clear Dependabot's direct-dependency alert? Those need different fixes. As written the PR achieves the second for sharp and the first only for @init/utils' nanoid.
Technical details
# Post-patch verification does not cover the resolved dependency graph
## Affected sites
- PR description "Verification" list — every listed command passes with
`sharp@0.34.5`, `@img/sharp-libvips-linux-x64@1.2.4` and `nanoid@5.1.6` still
installed. None of them inspect resolved versions.
## Required outcome
- A post-bump check that fails when a known-vulnerable version is still present
anywhere in the resolved tree, not merely absent from a `package.json`.
## Suggested approach (optional)
- The cheap manual form, run after `rm -rf node_modules && bun install --frozen-lockfile`:
`ls -d node_modules/.bun/sharp@* node_modules/.bun/nanoid@*`
- Per the repo's own learnings, only a full `rm -rf node_modules` gives a
trustworthy reading — bun leaves stale symlinks in `.bun` across incremental
installs and successive runs disagree with each other.
## Open questions for the human
- Remove the vulnerable code from the tree, or just clear the direct-dependency
alert? If only the latter, the `sharp` bump is doing nothing beyond silencing
Dependabot and `apps/docs` is carrying an unused dependency.
- `next@16.2.6` (via `@react-email/ui`, not production-serving) and
`@wxt-dev/auto-icons` both cap at `^0.34.5` and cannot take 0.35.x without an
override that violates their declared range. Is accepting their `0.34.5`
copies the intended end state?ℹ️ Nitpicks
bun.locknew line 875: the root@emnapi/runtimeentry is downgraded 1.11.3 → 1.11.2 while@oxc-resolver/binding-wasm32-wasi's nested 1.11.2 entry is dropped. It is a hoist shuffle and inert in practice (@emnapi/runtimeis wasm32-gated and never installs on linux-x64 or darwin), but it is unexplained churn riding along in a security-scoped diff.
Claude Opus | 𝕏
| "@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], | ||
|
|
||
| "@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], | ||
| "@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], |
There was a problem hiding this comment.
Unrelated downgrade: the root @emnapi/runtime drops from 1.11.3 to 1.11.2 here while the @oxc-resolver/binding-wasm32-wasi nested 1.11.2 entry is removed below. It appears inert (wasm32-gated, never installed on linux-x64), but it is churn unrelated to either advisory.
There was a problem hiding this comment.
Leaving this as-is, but here is the explanation. @img/sharp-wasm32 widened its requirement from ^1.7.0 to ^1.11.1 between sharp 0.34.5 and 0.35.3, so bun re-picked the hoist winner: @oxc-resolver/binding-wasm32-wasi's 1.11.2 moved up to the root and sharp's 1.11.3 moved into a nested @img/sharp-wasm32/@emnapi/runtime entry. Same entry count, no version added or removed from the graph, and @emnapi/runtime still installs on no platform we build for (ls -d node_modules/.bun/@emnapi+runtime@* finds nothing after a clean install). Pinning it back would mean adding an override for a package that is never installed, so I would rather carry the two lines of movement.
Claude Opus | 𝕏
|
The review was right: both bumps were declared but only
Side effect worth noting: the override collapsed the duplicate entries, so Verified after One finding I deliberately did not bundle: Task list (5/5 completed)
|
The direct bumps left every real consumer on the vulnerable copies: astro, next and @wxt-dev/auto-icons each kept a nested sharp@0.34.5 with the libvips 1.2.4 binary from GHSA-f88m-g3jw-g9cj, and @scalar/types kept a nested nanoid@5.1.6 from GHSA-28wg-ghj8-5hjv. Add a root sharp override so all three consumers dedupe onto 0.35.3, and drop the stale nested @scalar/types/nanoid entry so it dedupes onto the root 5.1.16 that its own ^5.1.6 range already allows. After rm -rf node_modules && bun install --frozen-lockfile the store holds exactly one sharp (0.35.3, libvips 8.18.3) and no nanoid@5.1.6. This also collapses the 190 nested duplicate entries the first attempt added.

Dependabot reports high-severity vulnerabilities in the direct
nanoidandsharpdependencies. This updates both packages to patched releases and forces the whole resolved graph onto them, so no vulnerable copy is left installed.sharp0.34.5→0.35.3inapps/docs(GHSA-f88m-g3jw-g9cj, High). The direct pin alone is inert: nothing in the repo importssharp, and the real consumers areastro's built-in image service plusnextand@wxt-dev/auto-icons, each of which bun kept on its own nested0.34.5. A rootoverridesentry dedupes all three onto0.35.3, which also collapses the ~190 nested duplicate lock entries the naive bump produced.nanoid5.1.6→5.1.16inpackages/utils(GHSA-28wg-ghj8-5hjv / CVE-2026-67214, High).@scalar/typesdeclares^5.1.6but bun preserved a stale nested5.1.6; dropping that lock entry lets it dedupe onto the root5.1.16. An override is not usable here because bun ignores scoped overrides and a flat one would drag thenanoid@3.xconsumers onto ESM-only 5.x.Compatibility:
sharp0.35 needs Node >= 20.9 and the repo targets Node 24 everywhere.nextis a devDependency reached only through@react-email/ui, and@wxt-dev/auto-iconscalls only thesharp()constructor, so overriding past their declared^0.34.5is safe.Verification
The declared-version checks alone cannot detect a vulnerable copy left in the tree, so the resolved graph is asserted directly after
rm -rf node_modules && bun install --frozen-lockfile:ls -d node_modules/.bun/sharp@*→ onlysharp@0.35.3ls -d node_modules/.bun/@img+sharp-libvips-linux-x64@*→ only1.3.2; the vulnerable1.2.4is gonels -d node_modules/.bun/nanoid@*→3.3.16and5.1.16; no5.1.6*/node_modules/sharpsymlink (astro,next,@wxt-dev/auto-icons) points atsharp@0.35.3sharpfromrealpath node_modules/.bun/astro@*/node_modules/astroreportsvips: 8.18.3(the patched libvips) and round-trips a resizebun auditno longer reports either advisoryAlso run:
bun run check,bun run check:monorepo,bun test,bun run build --filter=docs.Out of scope, noted for follow-up:
bun auditflags the transitivenanoid@3.3.16under a different advisory, GHSA-2v37-7h3g-55p8 (<3.3.18, High). It predates this branch and every consumer's^3.3.xrange accepts the fix, so it is a clean separate change.Created with GPT-5.6 Sol through the Codex harness in T3 Code.
Claude Opus| 𝕏