chore(deps): clear the dependency audit backlog - #228
Merged
Conversation
Fixes GHSA-v422-hmwv-36x6 (denial of service when an invalid limit value silently disables size enforcement). Pulled in transitively by express 5.2.1, whose `^2.2.1` range already admits the fix, so only the lockfile changes. Assisted-by: Claude:claude-opus-5[1m]
Fixes GHSA-5xrq-8626-4rwp (critical: arbitrary file read and execution while the Vitest UI server is listening), fixed in 3.2.6. Raise the declared range from `^3.0.0` to `^3.2.6` so the security floor is recorded in the manifest rather than only in the lockfile; the workspace still exercises the vitest v3 line as intended. Assisted-by: Claude:claude-opus-5[1m]
There was a problem hiding this comment.
Pull request overview
This PR clears the yarn npm audit -AR backlog by applying non-breaking dependency upgrades, adding narrowly-scoped audit suppressions (by advisory ID) with maintainer documentation, and includes a user-facing fix to keep Vitest 4.1 instrumentation working after runTest moved bundles.
Changes:
- Bump multiple dev/test dependencies (Vitest 3/4 fixtures, Next 16 fixture, sqlite3 fixture, and transitive toolchain deps via lockfile updates) and add two root
resolutionsoverrides. - Add
.yarnrc.ymlnpmAuditIgnoreAdvisoriesentries plus a maintainer doc explaining what’s deferred and what version floors would remove each suppression block. - Update Vitest hook instrumentation to also target
@vitest/runner/dist/chunk-artifact.js, and adjust tests/fixtures for new behaviors (Node 18 Vitest 4 skip + Next 16 agent-rules file generation suppression).
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Updates the resolved dependency graph to incorporate the audit-clearing bumps/dedupes and new transitive trees. |
| package.json | Adds resolutions overrides (node-gyp, postcss) to eliminate otherwise-unreachable advisories without breaking Node 18 support. |
| .yarnrc.yml | Introduces npmAuditIgnoreAdvisories with block-level rationale and “REMOVE WHEN” triggers to keep yarn npm audit -AR clean. |
| docs/maintenance/deferred-upgrades.md | Documents deferred/accepted advisories and the concrete upgrade floors needed to retire each suppression block. |
| src/hooks/vitest.ts | Extends Vitest runner instrumentation to the new chunk-artifact.js location used by Vitest 4.1. |
| test/vitest.test.ts | Skips Vitest 4 fixture runs on unsupported Node versions to keep Node 18 CI green. |
| test/vitest3/package.json | Bumps the Vitest 3 fixture dependency range to a fixed, audited version line. |
| test/vitest4/package.json | Bumps the Vitest 4 fixture dependency range to 4.1.x (required for the audit fix + hook update). |
| test/sqlite/package.json | Bumps sqlite3 fixture to 5.1.7 (tooling/tree changes reflected in the lockfile). |
| test/next16/package.json | Bumps Next 16 fixture dependency range to pick up patched Next/sharp transitive fixes. |
| test/next16/next.config.js | Disables Next’s AI-agent “agent-rules” file generation to keep the fixture reproducible under agent-driven runs. |
| test/snapshots/next16.test.ts.snap | Updates snapshot for upstream Next 16 response header/body changes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…t.js vitest 4.1 rebundled @vitest/runner: the `runTest` function declaration we wrap to intercept test before/afters relocated from `dist/chunk-hooks.js` to `dist/chunk-artifact.js`. Without a matching hook point the wrap never applies and vitest runs fall back to process recording, losing per-test AppMaps and their metadata. Register the new chunk as an instrumentation target alongside the existing `index.js` (v0-v2) and `chunk-hooks.js` (v3) names. This is required to bump the test/vitest4 workspace to vitest 4.1.10, which fixes GHSA-5xrq-8626-4rwp (critical: arbitrary file read and execution while the Vitest UI server is listening, fixed in 4.1.0). The bump also pulls vite 8.x, clearing GHSA-4w7w-66w2-5vf9, GHSA-v2wj-q39q-566r, GHSA-p9ff-h696-f583, GHSA-v6wh-96g9-6wx3 and GHSA-fx2h-pf6j-xcff for that workspace. Assisted-by: Claude:claude-opus-5[1m]
Clears the whole outstanding Next.js 16 advisory set for this workspace: GHSA-q4gf-8mx6-v5v3 and GHSA-8h8q-6873-q5fj (DoS with Server Components), GHSA-26hh-7cqf-hhc6 (middleware/proxy bypass via segment-prefetch routes), GHSA-3g8h-86w9-wvmq (cache-poisonable middleware redirects), GHSA-ffhc-5mcf-pf4q (XSS via CSP nonces), GHSA-gx5p-jg67-6x7h (XSS in beforeInteractive scripts), GHSA-vfv6-92ff-j949 (RSC cache-busting collisions), GHSA-mg66-mrh9-m8jx (DoS via connection exhaustion) and GHSA-h64f-5h5j-jqjh (DoS in the Image Optimization API). Also pulls sharp 0.35.3, fixing GHSA-f88m-g3jw-g9cj (inherited libvips CVE-2026-33327, CVE-2026-33328, CVE-2026-35590 and CVE-2026-35591). The snapshot update is upstream response-header churn only, not an instrumentation change: Next now sends `Cache-Control: no-cache` instead of `no-store` and the rendered page is 62 bytes longer. The recorded AppMap structure is byte-identical otherwise. Assisted-by: Claude:claude-opus-5[1m]
vite 7.3.1 -> 7.3.6 in the test/vitest3 dependency chain fixes GHSA-4w7w-66w2-5vf9 (path traversal in optimized-deps `.map` handling), GHSA-v2wj-q39q-566r and GHSA-fx2h-pf6j-xcff (`server.fs.deny` bypasses), GHSA-p9ff-h696-f583 (arbitrary file read via the dev-server WebSocket) and GHSA-v6wh-96g9-6wx3 (launch-editor NTLMv2 hash disclosure on Windows). The transitive esbuild 0.27.3 -> 0.28.2 that comes with it fixes GHSA-g7r4-m6w7-qqqr (arbitrary file read when running the dev server on Windows). vitest 3.2.7 already allows `^7.0.0-0`, so this is a lockfile-only change. Assisted-by: Claude:claude-opus-5[1m]
5.1.7 replaces the unmaintained @mapbox/node-pre-gyp with prebuild-install, which drops @mapbox/node-pre-gyp and its rimraf 3.0.2 / gauge 3.0.2 / are-we-there-yet 2.0.0 subtree out of the installed graph. Two caveats, both cosmetic as far as `yarn npm audit -AR` is concerned: - sqlite3 5.1.7 still declares `node-gyp: 8.x` as an *optional* dependency, so the deprecated node-gyp 8.4.1 subtree (npmlog, gauge, are-we-there-yet, rimraf, cacache 15.3.0, @npmcli/move-file, @tootallnate/once, inflight) is still reachable in the lockfile and still reported. It is optional and not linked, so nothing is actually installed from it. Clearing it needs sqlite3 6.x (node-gyp 12.x), which requires Node >=20.17.0 against our declared `engines.node: >=18` — deferred. - prebuild-install is itself deprecated with no successor, so the audit trades one deprecation notice for another. sqlite3 6.x depends on prebuild-install too, so this is unavoidable either way. Assisted-by: Claude:claude-opus-5[1m]
Three different optional `node-gyp` entries were being resolved across the lockfile -- 8.4.1 (sqlite3), 9.4.0 (fsevents and node-addon-api, both via `node-gyp: latest`) and 12.4.0 (npm's own tree). The 8.x and 9.x ones drag in a large deprecated subtree, which `yarn npm audit -AR` reports because it walks optional lockfile entries even though nothing links them: sqlite3 and fsevents both ship prebuilt binaries, so node-gyp never actually runs here. Consolidating on node-gyp 11.5.0 clears six findings: - npmlog 6.0.2 (deprecated) and its gauge 4.0.4 / are-we-there-yet 3.0.1 - rimraf 3.0.2 (deprecated, <v4 unsupported) - cacache 15.3.0 -> @npmcli/move-file 1.1.2 (deprecated, moved to @npmcli/fs) - http-proxy-agent 4.0.1 -> @tootallnate/once 1.1.2 (GHSA-vpq2-c234-7xj6) node-gyp 11.5.0 rather than 12.x on purpose: 12.x drops make-fetch-happen and cacache entirely (so it would also clear the remaining glob 10.5.0), but it declares `engines.node: ^20.17.0 || >=22.9.0` and CI still covers Node 18. 11.5.0 declares `^18.17.0 || >=20.5.0`, matching our `engines.node: >=18`. Worth revisiting when the Node 18 floor is raised. Assisted-by: Claude:claude-opus-5[1m]
…isories next@14.2.35 depends on `"postcss": "8.4.31"` -- an exact pin, so the resolver has no range to move within and this cannot be fixed by a bump. A resolution override is the only route short of moving test/next off Next 14. Clears four findings: - GHSA-28wg-ghj8-5hjv (high) and GHSA-2v37-7h3g-55p8 (high) -- nanoid non-secure/custom generators can loop indefinitely; pulled in via postcss -> nanoid, now 3.3.18 - the two remaining postcss advisories against 8.4.31 Scope of verification: test/next and test/next16 both pass, but neither test app contains any CSS or a postcss config, so postcss is loaded by Next's build pipeline without being meaningfully exercised. The override stays inside the 8.x major and both workspaces are private and test-only, so the blast radius is limited to CI; Next's exact pin looks like lockfile hygiene on Vercel's side rather than a hard API requirement. Assisted-by: Claude:claude-opus-5[1m]
`yarn npm audit -AR` now exits clean. Every remaining finding is listed individually in `npmAuditIgnoreAdvisories` with a rationale, and the reasoning plus the version floors that unblock each group are written up in docs/maintenance/deferred-upgrades.md. Listed by advisory ID rather than via `npmAuditExcludePackages` on purpose. Excluding a package masks its future advisories too, and for `next` and `vite` that would hide genuinely actionable alerts against test/next16 (current Next 16.x) and the vitest 3/4 chains (vite 7/8). Verified precise rather than blanket: removing any single ID makes exactly that finding reappear. The list is long, so it is structured to be retired wholesale rather than audited entry by entry. Each block carries a `REMOVE WHEN:` line naming the version floor that frees it, and the doc has the matching table. 26 of the 31 entries go away with just the vitest<3 and Next<15 drops. Accepted groups, all dev/test-only -- `yarn npm audit -R --environment production` reports no suggestions, so nothing here reaches published dist/: - vitest 0.34.6/1.6.1/2.1.9 GHSA-5xrq-8626-4rwp (critical). No fix exists on those lines; each is the final release of its major. Needs the Vitest UI server listening, which these tests never start. - next 14.2.35, 21 advisories. 14.2.35 is the last stable 14.x, so there is no headroom within the major. - vite 5.4.21 and esbuild 0.21.5, downstream of vitest 0.34/1.6 pinning vite ^5; 5.4.21 is the last 5.x. - serialize-javascript 6.0.2 via mocha. No released mocha allows 7.x, and an override is blocked because 7.x requires Node >=20. - prebuild-install, glob and inflight deprecation notices with no successor. The doc also records two decisions that are easy to undo by accident: - Dependabot, not yarn audit, is the security signal here, and accepted alerts are dismissed manually. Dismissals are self-cleaning where a config file rots, and it is already the established workflow. Moving the test fixtures' deps to devDependencies to make a development-scope auto-triage rule match was investigated and rejected: 24 of 31 alerts attribute to yarn.lock, which carries no dev/runtime partition, so only the 7 direct next alerts could flip -- and those disappear with the Next 14 drop anyway. - yarn audit is deliberately not a CI gate. It duplicates Dependabot and would fail builds on findings we have explicitly accepted. Assisted-by: Claude:claude-opus-5[1m]
Next 16 bundles @vercel/detect-agent and, on `next dev`, writes a managed AGENTS.md / CLAUDE.md block into the project directory when it detects an AI coding agent in the environment -- CLAUDECODE, AI_AGENT, CURSOR_TRACE_ID, GEMINI_CLI, CODEX_*, COPILOT_* and friends. See next/dist/server/lib/generate-agent-files.js, gated on `agentRules !== false` (default true). The effect is that running the suite under an AI coding agent leaves two untracked files in test/next16 while running it as a human leaves none, so the fixture is no longer reproducible across environments. Setting `agentRules: false` fixes the cause rather than hiding the symptom with .gitignore, and avoids committing Next's AI instructions into a fixture that serves one hello route. This is the first next.config in the repo. Verified with the detection env vars still set, so generation would otherwise have fired: test/next16.test.ts passes and the files are no longer created, i.e. the added config does not perturb the loadConfig hook or the injected webpack loader. Assisted-by: Claude:claude-opus-5[1m]
vitest 4 declares `engines.node: ^20.0.0 || ^22.0.0 || >=24.0.0` and genuinely
cannot start on Node 18. Bumping test/vitest4 to 4.1.10 pulled vite 8, which
brings rolldown, and rolldown imports `styleText` from `node:util` -- added in
Node 20.12. That is a SyntaxError at module load, so `vitest run` dies before
executing anything and the run produces no AppMaps at all rather than failing an
assertion:
SyntaxError: The requested module 'node:util' does not provide an export
named 'styleText'
at async start (.../vitest/dist/chunks/cac.*.js)
This surfaced as a Node 18 CI failure. It is a regression from the 4.1.10 bump:
4.0.18 resolved vite 7 without rolldown and did run on Node 18 despite
declaring the same engines range.
Skip rather than pin back, because vitest 4 does not support Node 18 by its own
declaration -- exercising it there tests a combination no user can have, and any
4.x patch would break it again. Reverting to 4.0.18 would also reinstate
GHSA-5xrq-8626-4rwp (critical).
Scoped to v4 only, deliberately: vitest 0.34.6, 1.6.1, 2.1.9 and 3.2.7 all
declare support for Node 18 (`^18.0.0`), so they keep running there.
Verified on both: Node 18 gives 9 passed / 2 skipped, Node 24 gives 11 passed.
Uses the same `cond ? test : test.skip` shape as test/postgres.test.ts and
test/simple.test.ts.
Assisted-by: Claude:claude-opus-5[1m]
dividedmind
force-pushed
the
chore/bump-deps
branch
from
August 17, 2026 11:27
629044b to
0c36467
Compare
commit: |
|
🎉 This PR is included in version 2.26.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Works through
yarn npm audit -ARand fixes everything fixable without a breaking change toappmap-nodeitself. What remains is explicitly accepted by advisory ID, with the reasoning and the version floors that unblock each group written up in a new maintainer doc.yarn npm audit -ARnow exits0withNo audit suggestions.Nothing here was ever shipped to consumers —
yarn npm audit -R --environment productionreported no suggestions both before and after. Every finding lived indevDependenciesor in a private, test-only workspace undertest/.11 commits, deliberately unsquashed: the rationale for each change — especially the "why a bump cannot work here" cases — lives in the commit messages.
Dependency fixes
yarn dedupewas run after each bump, with targeted tests after each.body-parser2.2.2 → 2.3.0^2.2.1already admitted the fixvitest3.2.4 → 3.2.7 (test/vitest3)vitest4.0.18 → 4.1.10 (test/vitest4)next16.1.7 → 16.3.1 (test/next16)sharp(GHSA-f88m-g3jw-g9cj)vite7.3.1 → 7.3.6,esbuild0.27.3 → 0.28.2sqlite35.1.6 → 5.1.7Two
resolutionsoverridesBoth are cases where bumping was structurally impossible, not merely awkward:
node-gyp: ^11.5.0— clears 6 findings (npmlog,gauge,are-we-there-yet,rimraf,@npmcli/move-file,@tootallnate/once). Three separate optional node-gyp entries (8.4.1 via sqlite3, 9.4.0 viafsevents/node-addon-apideclaringnode-gyp: latest, 12.4.0 via npm's own tree) were dragging in a large deprecated subtree.yarn npm audit -ARwalks optional lockfile entries even though nothing links them — sqlite3 and fsevents both ship prebuilt binaries, so node-gyp never actually runs here. Pinned to 11.5.0 rather than 12.x on purpose: 12.x would also clear the lastglobnotice but declaresengines.node: ^20.17.0 || >=22.9.0, and CI still covers Node 18.postcss: ^8.5.26— clears 4 findings, including two high-severitynanoidadvisories viananoid3.3.18.next@14.2.35depends on"postcss": "8.4.31", an exact pin, so the resolver had no range to move within and no bump could reach it.sqlite3caveatFlagged because it's the one change that doesn't reduce the audit count — it nets +1. 5.1.7 replaces the unmaintained
@mapbox/node-pre-gypwithprebuild-install, which genuinely improves the installed graph, but it still declaresnode-gyp: 8.xas an optional dep andprebuild-installis itself deprecated. Kept because the installed-tree improvement is real andprebuild-installis unavoidable (sqlite3 6.x depends on it too), but this is the commit to drop if you disagree.One product change
65560be fix(vitest): support vitest 4.1, which moved runTest to chunk-artifact.jsDeliberately a separate
fix:commit rather than folded in with the bumps. vitest 4.1 rebundled@vitest/runner, relocating therunTestdeclaration we wrap fromdist/chunk-hooks.jstodist/chunk-artifact.js. Without a matching hook point the wrap silently never applies and vitest runs fall back to process recording, losing per-test AppMaps and their metadata. Required to bumptest/vitest4at all.Node 18 regression, caught and fixed
0c36467 test(vitest): skip the vitest 4 cases on Node 18The vitest 4 bump broke Node 18 CI, and this is a genuine regression introduced by this branch rather than a pre-existing failure. 4.1.10 pulls vite 8, which brings rolldown, which imports
styleTextfromnode:util— added in Node 20.12:It's a
SyntaxErrorat module load, sovitest rundies before executing anything and the run produces no AppMaps at all rather than failing an assertion — which is why it surfaced as an empty{}snapshot. Confirmed causal by temporarily downgrading: 4.0.18 runs fine on Node 18, because it resolved vite 7 without rolldown, despite declaring the sameenginesrange.Skipped rather than pinned back, because vitest 4 doesn't support Node 18 by its own declaration — exercising it there tests a combination no user can have, and any 4.x patch would break it again. Pinning back would also reinstate GHSA-5xrq-8626-4rwp (critical).
Scoped to v4 only, verified rather than assumed — every older major genuinely supports Node 18 and keeps running there:
engines.node>=v14.18.0^18.0.0 || >=20.0.0^18.0.0 || ^20.0.0 || >=22.0.0^20.0.0 || ^22.0.0 || >=24.0.0Accepted findings and the doc
cd1ccfdaddsnpmAuditIgnoreAdvisoriesto.yarnrc.ymlplusdocs/maintenance/deferred-upgrades.md.Listed as 31 individual advisory IDs rather than package-level excludes, on purpose: excluding a package masks its future advisories too, and for
nextandvitethat would have hidden genuinely actionable alerts againsttest/next16(current Next 16.x) and the vitest 3/4 chains (vite 7/8). Verified precise rather than blanket — removing any single ID makes exactly that finding reappear, and nothing else.The list is long, so it's built to be retired wholesale. Every block carries a
REMOVE WHEN:line naming its trigger, and the doc has the matching table:test/nextoff Next 14engines.nodeto 20engines.nodeto 20.17glob, plus drop/retarget the node-gyp pininflightprebuild-install26 of the 31 go away with the first two rows. The cleanup is also self-checking: delete a block, re-run
yarn npm audit -AR, and if it still exits clean the entries were dead.What's blocked and why
Every accepted finding is genuinely unreachable by a bump:
next14.2.35 (test/next) — 21 advisories, all fixed in 15.5.x+. 14.2.35 is the last stable 14.x; only canaries exist beyond it, so there's zero headroom within the major.vitest0.34.6 / 1.6.1 / 2.1.9 — the same critical advisory, and no fix exists on those lines. Upstream fixed only 3.2.6 and 4.1.0; each of these is the final release of its major. Requires the Vitest UI server to be listening, which these tests never start.vite5.4.21 /esbuild0.21.5 — downstream of the above. vitest 1.6.1 pinsvite: ^5.0.0, and 5.4.21 is the last 5.x.serialize-javascript6.0.2 — no released mocha allows the fix: 10.8.2 and 11.8.0 both pin^6.0.2, onlymocha@12.0.0-rc.6moves to^7.0.2. An override is blocked too, because 7.x declaresengines.node: >=20.0.0. Only reachable from mocha's parallel-mode workers, whichtest/mochanever uses.The doc also records two decisions that are easy to undo by accident: that Dependabot rather than yarn audit is the security signal here (with the data showing why the devDependencies/auto-triage route was investigated and rejected), and that yarn audit is deliberately not a CI gate, since it duplicates Dependabot and would fail builds on findings we've explicitly accepted.
Test fixture fix
b505b1c test(next16): disable Next.js agent-rules file generationNext 16 bundles
@vercel/detect-agentand, onnext dev, writes a managedAGENTS.md/CLAUDE.mdblock into the project dir when it detects an AI coding agent (CLAUDECODE,AI_AGENT,CURSOR_TRACE_ID,CODEX_*,COPILOT_*, …). So the suite left two untracked files behind when run under an agent and none when run by a human — the fixture wasn't reproducible across environments.agentRules: falsefixes the cause instead of hiding it with.gitignore, and avoids committing Next's AI instructions into a fixture that serves one hello route.Verification
yarn install --immutable(what CI runs)resolutionsyarn dedupe --checkyarn prepackyarn lintyarn teston Node 24yarn teston Node 18yarn npm audit -ARNo audit suggestions, exit 0yarn npm audit -R --environment productionNo audit suggestionsReviewer notes
toMatchSnapshotfailure in the vitest v1+ block; the vitest file passed in isolation and a second full run passed clean. Recording it as a flake rather than asserting it's nothing — worth watching on CI.^20.19.0 || >=22.12.0. So vitest3-on-Node-18 works by luck rather than contract — the same shape of trap that produced the v4 regression above. Upstream's inconsistency, not ours, but a plausible next breakage.test/__snapshots__/next16.test.ts.snap), and it's upstream churn, not an instrumentation change: Next now sendsCache-Control: no-cacheinstead ofno-store, and the rendered page is 62 bytes longer. The recorded AppMap structure is otherwise identical.postcssoverride is under-exercised. Both Next test apps pass, but neither contains any CSS or a postcss config, so postcss is loaded by the build pipeline without being meaningfully exercised. The override stays inside the 8.x major and both workspaces are private and test-only, so the blast radius is limited to CI.next16agent-file change was checked with the detection env vars still set, so generation would otherwise have fired.After merge
Dependabot's view is narrower than yarn's and it had been reading
main, so several of its open alerts (body-parser,nanoid,postcss,sharp, oneesbuild) are fixed by this PR and should close on re-scan. Worth letting that happen before dismissing anything, then dismissing the residualnext14 alerts with reasonnot_used, rather than dismissing alerts that were about to resolve themselves.Assisted-by: Claude:claude-opus-5[1m]