Skip to content

fix(deps): two HIGH advisories were failing every PR's Gate 1 - #884

Merged
green-dalii merged 1 commit into
mainfrom
fix/audit-advisories-zod-undici
Oct 24, 2026
Merged

green-dalii merged 1 commit into
mainfrom
fix/audit-advisories-zod-undici

Conversation

@green-dalii

Copy link
Copy Markdown
Member

main's own Gate 1 went red between 2026-10-23T15:53 and the next run, and every open PR reads as a failure with it. CI runs pnpm audit before the five checks, so a new advisory hides lint, types, build, tests and css-lint behind one line that has nothing to do with the change:

package vulnerable patched advisory
zod <4.6.6 4.6.7 GHSA-mrhx-c7xc-m3w5
undici <8.12.2 8.12.3 GHSA-xjj6-f33q-929c

Both are HIGH. Both bumps are inside the same minor line, so neither is a breaking change. pnpm audit --audit-level high --ignore-registry-errors now exits 0; 8 vulnerabilities remain, 2 low and 6 moderate, none high.

The failure mode worth recording: the overrides live in two files, and only one of them is the one you would think of first. package.json carries them, and pnpm-workspace.yaml carries the same list with the reasoning attached. pnpm 10 resolves from the workspace file, so editing package.json alone updated zod — a direct dependency, so it resolved either way — and left undici pinned at 8.10.2. pnpm install reported success in both cases, and the lockfile's own overrides: block was the only place that showed the stale value. The workspace comment already said "keep this list in step with package.json's overrides"; a comment is not a mechanism, so the next version bump will hit this again.

Both lockfiles regenerated — pnpm-lock.yaml, and package-lock.json via npm install --legacy-peer-deps --package-lock-only, per AGENTS.md's note that pnpm overrides are flat and npm cannot honour them.

THIRD-PARTY-NOTICES.md regenerated, because a version bump changes the attribution it records. The test that caught this was third-party-notices.test.ts — which is the check working: it failed with "zod@4.6.7 must have its own section" before the regeneration and passes after.

Gate 1: lint 0, tsc 0, build clean, 349 test files / 4872 tests, css-lint 0.

`main`'s own Gate 1 went red between 2026-10-23T15:53 and the next run, and
every open PR reads as a failure with it. CI runs `pnpm audit` before the
five checks, so a new advisory hides lint, types, build, tests and css-lint
behind one line that has nothing to do with the change:

    zod      <4.6.6   GHSA-mrhx-c7xc-m3w5
    undici   <8.12.2  GHSA-xjj6-f33q-929c

Both bumps are inside the same minor line, so neither is a breaking change.

**The overrides live in two files, and only one of them is the one the docs
mention.** `package.json` carries them, and `pnpm-workspace.yaml` carries the
same list with the reasoning attached; pnpm 10 resolves from the workspace
file, so editing `package.json` alone changed zod (a direct dependency) and
left undici pinned at 8.10.2. The workspace comment already said to keep the
two in step; the failure mode was that `pnpm install` reported success either
way.

Both lockfiles regenerated (`pnpm-lock.yaml`, and `package-lock.json` through
`npm install --legacy-peer-deps --package-lock-only`, per AGENTS), and
`THIRD-PARTY-NOTICES.md` regenerated because a version bump changes the
attribution it records — the test that caught this was
`third-party-notices.test.ts`, which is the check working as intended.

`pnpm audit --audit-level high --ignore-registry-errors` now exits 0: 8
vulnerabilities remain, 2 low and 6 moderate, none high.

Gate 1: lint 0, tsc 0, build clean, 349 test files / 4872 tests, css-lint 0.
@green-dalii

Copy link
Copy Markdown
Member Author

Maintainer merge audit — GitHub does not let the author approve the author's own PR, so this comment is the audit trail for the merge that follows. The maintainer authorised the bypass for this PR explicitly.

Gates checked before merging 16960d0d:

  • Gate 1 — lint 0, tsc 0, build clean, 349 test files / 4872 tests, css-lint 0, and pnpm audit --audit-level high --ignore-registry-errors exits 0. The GitHub check Gate 1 / Five-Gate is SUCCESS on this head, which is the point of the PR: it is the first green run on this tree since the advisories landed.
  • Closing keywords — none. This PR closes no issue by keyword; the advisory record lives in pnpm-workspace.yaml next to the override.
  • AI trailers — none.
  • Side effects — two lockfiles and one generated file. undici 8.10.2 → 8.12.3 and zod 4.6.5 → 4.6.7, both inside the same minor line. THIRD-PARTY-NOTICES.md regenerated by the repo's own generator, and third-party-notices.test.ts is the check that required it.
  • Breaking changes — none at the API level. The plugin's runtime dependencies are bundled by esbuild, so a minor bump inside zod's 4.x and undici's 8.x does not change the Obsidian-facing surface. Full suite green is the evidence.
  • Performance — no change. Both packages are dev-side or bundler-resolved; undici arrives through jsdom in the test tree.
  • Why bypass — main's CI is red, and every open PR inherits that red. Merging this is what restores the five-gate signal for feat(core): two-stage Rocchio query expansion — the corpus supplies the bridge #855, fix(ingest): the automatic path now honours Obsidian's excluded-files list #879, feat(tools): the answer context's cost, measured through the production path #881 and feat(tools): the follow-up rate, measured on the user's own conversation #882. The alternative is to wait for a reviewer on a dependency patch while five PRs sit blocked on a failure none of them caused.

@green-dalii
green-dalii merged commit 866bfb3 into main Oct 24, 2026
2 checks passed
@green-dalii
green-dalii deleted the fix/audit-advisories-zod-undici branch October 24, 2026 07:43
green-dalii added a commit that referenced this pull request Oct 25, 2026
…pies

`ai` 7.0.136 -> 7.0.142, resolved on the current `main` rather than on
dependabot's branch: #884 raised the `zod` and `undici` overrides and rewrote all
three lockfiles, so the branch conflicted on `pnpm-lock.yaml`.

The bump alone was not shippable, and the two reasons were both measured.

One: it is a quarter of a megabyte of duplication. `ai` 7.0.142 asks for
`@ai-sdk/provider-utils@5.0.61` while the pinned `@ai-sdk/anthropic`,
`@ai-sdk/openai` and `@ai-sdk/openai-compatible` still resolve 5.0.49 and 5.0.58,
so three copies of both `@ai-sdk/provider` and `@ai-sdk/provider-utils` were
bundled:

  ai 7.0.136   main.js 5,290,267   copies: 5.0.49, 5.0.58
  ai 7.0.142   main.js 5,397,236   copies: 5.0.49, 5.0.58, 5.0.61   (+104.5 KB)

Two: it silently broke error normalization. Four tests in the Codex client suite
failed with the provider's own message instead of the plugin's `status 403: ...`
form. That reads like an upstream wording change and it was not. Probing the
thrown object gave `CTOR=APICallError STATUS=403 isAPI=false` - the error IS an
APICallError and carries the status, but the class came from a different copy
than the one `ai` re-exports. `mapAiSdkError` keys off `instanceof`, so the whole
normalization block stopped running: the status prefix, the `statusCode` and
`responseBody` fields, and every other AI SDK error class it matches. A duplicate
dependency is not only bytes.

Collapsing both packages to the version `ai` asks for removes the cause of both:

  ai 7.0.142, copies collapsed   main.js 5,170,949   (-116.5 KB, -2.26% vs main)
                                                    copies: 5.0.61 / 4.0.28

That is 221 KB smaller than the bump without it, and smaller than `main` was
before the bump. All four previously failing tests pass and `mapAiSdkError`
matches `instanceof` again.

The override goes in both places it has to: `package.json` for the npm-side
lockfile and `pnpm-workspace.yaml` for pnpm 10, which resolves from the workspace
file. #884 learned that the hard way - editing one of the two reports success
while the other stays stale, and the lockfile's own `overrides:` block is the
only place it shows.

`THIRD-PARTY-NOTICES.md` drops from 16 bundled packages to 12. It is generated
from the built bundle, so it needs a `pnpm build` first; running the generator
without one silently rewrites the file with the previous versions.

Two follow-ups, neither a regression against what lands here. #891 aligns all
four packages so one copy is bundled by construction, and it waits on what the
SDK's new `'interrupted'` finish reason means for the retry path. #892 replaces
`instanceof` with the SDK's `isInstance`, which is the only version of this
correct that survives a future dependency shuffle.

Gate 1: lint 0, tsc 0, build clean, 349 files / 4872 tests, css-lint 0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant