Skip to content

Commit 787104b

Browse files
objectstack-fleet[bot]claudeos-justin
authored
fix(deps): take the fixes for proxy-addr, source-map-js and katex that turn main's OSV scan red (#21951)
Part of #21945 Clause-②: no ## What this does `Validate Package Dependencies` runs OSV-Scanner against `pnpm-lock.yaml`. On `main` it reports four advisories, so the scheduled scan is red, and so is every PR that touches a `package.json`. Three of the four name a fixed version, and this PR takes those three fixes. The fourth, `sprintf-js`, has no fixed release. Its `[[IgnoredVulns]]` entry is on branch `claude/issue-21945-osv-exemption`, in its own `osv-exemption` PR, as convention 3 in `osv-scanner.toml`'s header requires. **Which half this leaves:** GHSA-hp3w-g68c-fv3c (`sprintf-js`). This PR alone does not turn the OSV step green, and neither does the exemption PR alone. The card stays open when this PR merges, and the PM finishes it after both have landed. ## OSV reading: before and after Measured locally with OSV-Scanner **v2.3.8**, the version `validate-deps.yml` pins. `api.osv.dev` answers 403 from this container, so the scan ran in offline mode (`--offline-vulnerabilities --download-offline-databases`) against the OSV npm database the scanner downloaded on 2026-10-06. `main` at `d16b9fbf` (exit 1). These are the same four rows the scheduled run 37407261685 reported: ```text | https://osv.dev/GHSA-238p-pmpm-9mq7 | 2.1 | npm | katex | 0.16.47 | 0.18.2 | pnpm-lock.yaml | | https://osv.dev/GHSA-jqcg-44mw-7w3h | 9.1 | npm | proxy-addr | 2.0.7 | 2.0.8 | pnpm-lock.yaml | | https://osv.dev/GHSA-68fv-2mgg-jv7q | 8.7 | npm | source-map-js | 1.2.1 | 1.2.2 | pnpm-lock.yaml | | https://osv.dev/GHSA-hp3w-g68c-fv3c | 6.9 | npm | sprintf-js | 1.1.3 | -- | pnpm-lock.yaml | ``` This PR at `e142f120` (exit 1, one row left, which the exemption PR covers): ```text | https://osv.dev/GHSA-hp3w-g68c-fv3c | 6.9 | npm | sprintf-js | 1.1.3 | -- | pnpm-lock.yaml | ``` This PR's lockfile scanned with the exemption PR's `osv-scanner.toml`: exit 0, `No issues found`, with one vulnerability filtered. ## Changes ### `pnpm-lock.yaml`: `proxy-addr` 2.0.8 and `source-map-js` 1.2.2 Every parent's declared range already admits the fix: `express` 5.2.1 declares `proxy-addr ^2.0.7`, and `postcss` 8.5.28, `@tailwindcss/node` 4.3.3, `css-tree` 3.2.1 and `magicast` 0.5.3 declare `source-map-js ^1.2.1`. So this is a re-lock and needs no new pin. - **Rejected:** `pnpm update proxy-addr source-map-js -r --depth Infinity`. It re-resolved unrelated packages: `@inquirer/*`, `@napi-rs/wasm-runtime`, `node-abi`, a second `postcss`, `nanoid` and `ip-address` copy, and `knex`'s peer set. That was +81/−60 lines. - **Taken:** a temporary override pair (`proxy-addr` to 2.0.8, `source-map-js` to 1.2.2), installed and then removed, followed by a second install. The lockfile keeps the two resolutions and nothing else moves: **+11/−11** lines, the two package entries and the five dependent edges. `pnpm-workspace.yaml` ends that step byte-identical to `main`. ### `pnpm-workspace.yaml` `overrides:` plus `pnpm-lock.yaml`: `katex` to `^0.18.2` - **Where:** in `pnpm-workspace.yaml`. The root `package.json` has no `pnpm.overrides` (its `pnpm` field holds only `ignoredBuiltDependencies`), and the block's own header records that pnpm v10 reads overrides from this file. - **Selector shape:** `'katex@>=0.11.0 <0.19.0': '^0.18.2'`. The floor is the advisory's `introduced` (0.11.0), and the bound sits at the caret boundary of the 0.18 target line. That is the durable shape the block header and `check:override-consistency` describe: the bound sits above the target's line, so a later lift moves only the target. - **Resolution:** `^0.18.2` resolves to **0.18.10**, not 0.18.11, because npm deprecates 0.18.11 ("Accidentally published with breaking changes. Use 0.19.0 instead."). katex 0.18's CLI dependency moves `commander` 8.3.0 to 15.0.0, which was already in the tree, so `commander@8.3.0` drops out. Lockfile **+6/−11**. - **Why an override, and not a dedupe:** no published `mermaid` admits the fix. Measured with `npm view mermaid@V dependencies.katex`: 11.16.0 and 11.16.1 declare `^0.16.45`, and 11.17.0, 11.17.1, 11.17.2, 12.0.0 and 12.1.0 (latest) declare `^0.16.47`. This override forces mermaid past its own declared range, so it needs evidence that mermaid still works. - **Note:** the entry carries a note in the block's style. It states the advisory, the forced-upgrade caveat and the evidence below. Totals: `pnpm-lock.yaml` **+17/−22**; `pnpm-workspace.yaml` **+33/−0** (one entry plus its note). ## Evidence that katex 0.18 works for the only consumer The only path to katex is `apps/docs`, then `mermaid` `^11.16.0` (11.16.1), then `katex`. Nothing else in the workspace names katex (`git grep -i katex`, lockfile excluded: zero hits). 1. **Where mermaid touches katex.** It does so in one place, `renderKatexUnsanitized` in `dist/chunks/mermaid.core/chunk-I66GZJ75.mjs`. That is a lazy `import("katex")` followed by `katex.renderToString(c, { throwOnError: true, displayMode: true, output })`, where `output` is `"mathml"` or `"htmlAndMathml"`. The katex 0.17 and 0.18 breaking changes (the internal `__defineFunction` API, and the prefixed internal CSS classes) touch neither that call nor the outer `.katex` class mermaid styles (`.node .katex path`). The 0.19.0 strict-mode change is outside the target line. 2. **Node.** Through mermaid's own resolution, `katex.version` is `0.18.10`, and `renderToString` with mermaid's options returns MathML for both output modes. 3. **Browser.** A bundle of the real `mermaid@11.16.1` `mermaid.core.mjs` ran in headless Chromium with the same `initialize()` options `apps/docs/components/mermaid.tsx` passes (`securityLevel: 'strict'`). It rendered a flowchart whose label is `$$x^2 + \frac{a}{b}$$` with this result: `{"katexVersion":"0.18.10","hasMath":true,"hasMsup":true,"hasFrac":true,"unsupported":false,"errored":false,"pageErrors":[]}`. 4. **Docs build, local.** `next build` in `apps/docs` ran under the shared verify lock (`VERDICT command-exit 0`; compiled in 119s; 1240/1240 static pages; `BUILD_ID` written). The client chunk carries katex `version:"0.18.10"`, and no `0.16.47` remains in `.next/static/chunks`. This was `next build` alone, not the full `vercel.json` command: the docs app reads only `packages/spec/package.json` from the spec, and the committed `content/docs/references` stood in for `gen:schema`/`gen:docs`. The PR's `Build Docs` job runs the production command. 5. **Advisory direction.** Under a polluted `Object.prototype.trust`, `\href{…}{x}` through katex 0.16.47 emits a link, and through 0.18.10 it does not. No page in `content/` puts `$$` inside a mermaid block today, so this path is latent rather than live. The proof is still of the code that would run. ## Changeset `skip-changeset`. The diff touches `pnpm-lock.yaml` and `pnpm-workspace.yaml`, both repo-root configuration. Neither is in any package's `files[]`, and overrides do not reach downstream installs, so nothing publishes. ## Local verification, at `e142f120` - `pnpm install --frozen-lockfile --prefer-offline`: exit 0. - The gates come from `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at this head: 22 commands, the same list the dispatch named. The `--ran` reconciliation is filled in below. - `check:override-consistency`: green. katex appears in neither census: mermaid consumes it, and the bound clears the target floor. `--ran` reconciliation, with exit codes recorded before any pipe: **22 derived, 18 run, 4 NOT-MEASURED, 0 UNRUN**. | Gate | Exit | |---|---| | `node scripts/check-changeset-fixed.mjs` | 0 | | `node scripts/check-closing-keyword-parity.mjs` (+ `--self-test`) | 0 / 0 | | `node scripts/check-comment-mask-corpus.mjs` | 0 | | `node scripts/check-dts-emitted.mjs --self-test` | 0 | | `node scripts/check-osv-exemptions.mjs` (+ `--self-test`) | 0 / 0 | | `node scripts/check-prerelease-pin-watch.mjs --self-test` ; `--verbose` | 0 / 0 | | `pnpm --filter @objectstack/spec run check:llms-txt` | 0 | | `pnpm check:driver-memory-census` · `check:gitlink-declared` · `check:nul-bytes` · `check:override-consistency` · `check:refd-timer-probe` · `check:vendor-export-contract-resolve` · `check:watch-hint-literal` · `check:workspace-manifest-cycles` | 0 each | | `pnpm check:dts-closure` · `check:dual-build-cjs-loads` · `check:lean-entry-closure` · `check:sourcemap-no-sources-content` | **3, PREREQUISITE NOT MET** | **NOT MEASURED** (four gates). They read every package's built `dist/`. This diff touches no package source, so the local scope builds no package, and the build these four need is the full `pnpm build`. CI's `Build Core` and `Lint & Repo Gates` measure them on the built tree. Both NOT MEASURED readings are declared here and are not counted as passes. Not run locally, CI's: the path-scheduled jobs `dispatch-gates` lists (`Test Core`, `Temporal Conformance`, `Dogfood Regression Gate`, `Dogfood Verify CLI`, `Build Core`, `Build Docs`) and the type-check lanes. ## Acceptance notes - `pnpm install` prints `ioredis-mock 8.13.1: unmet peer ioredis@^5: found 6.0.0`. That warning is already present on `main`: the lockfile there resolves the same pair, and `packages/services/service-cluster-redis/src/ioredis-pair.pin.test.ts` pins it. It is not from this diff. --- _Generated by [Claude Code](https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw)_ --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Justin <justin@objectstack.ai>
1 parent 4c49150 commit 787104b

2 files changed

Lines changed: 50 additions & 22 deletions

File tree

‎pnpm-lock.yaml‎

Lines changed: 17 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pnpm-workspace.yaml‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,36 @@ overrides:
536536
# written. Transitive-only and dev-only: nothing publishable declares
537537
# undici, and both paths reach the tree through devDependencies.
538538
'ip-address@<11.0.0': '^10.5.1'
539+
# OSV 2026-10-06 (#21945, scheduled scan run 37407261685) — one advisory that
540+
# names a fixed version, so this is the "take the fix" path osv-scanner.toml's
541+
# header prescribes and NOT an exemption.
542+
# katex GHSA-238p-pmpm-9mq7 (2.1 low) — an inherited `Object.prototype.trust`
543+
# is read as an explicit `trust: true`, so a prototype pollution that
544+
# already exists elsewhere lets attacker math emit links or load external
545+
# resources. Range introduced:0.11.0 -> fixed:0.18.2, read from the OSV
546+
# offline npm database the scanner downloads. Flagged at the single
547+
# resolved copy 0.16.47.
548+
# ⚠️ Unlike the dedupes above, this is a FORCED upgrade past the dependent's
549+
# declared range. The one consumer is mermaid@11.16.1 (apps/docs declares
550+
# mermaid ^11.16.0), which declares katex ^0.16.45, and no published
551+
# mermaid admits the fix: 11.17.0 through 12.1.0 all declare ^0.16.47
552+
# (npm view, 2026-10-06). mermaid touches katex in one place, a lazy
553+
# `import("katex")` that calls the default export's renderToString() with
554+
# { throwOnError, displayMode, output } for a `$$...$$` label. The 0.17 and
555+
# 0.18 breaking changes (the internal __defineFunction API, prefixed
556+
# internal CSS classes) touch neither that call nor the outer `.katex`
557+
# class mermaid styles. Measured: a mermaid 11.16.1 flowchart with a
558+
# `$$...$$` label renders MathML through katex 0.18.10 in Chromium, under
559+
# the same initialize() options apps/docs/components/mermaid.tsx passes.
560+
# The target resolves to 0.18.10, not 0.18.11: 0.18.11 is deprecated on
561+
# npm ("Accidentally published with breaking changes"), and pnpm skips it.
562+
# Transitive-only and docs-only: nothing publishable declares katex, so
563+
# check-override-consistency.mjs's manifest rule has no declared range to
564+
# hold in lockstep and says nothing about this entry (measured; neither
565+
# census lists it: mermaid consumes it, and the bound clears the target
566+
# floor). The floor is the advisory's 0.11.0; the bound is 0.19.0, the
567+
# caret boundary of the 0.18 target line, per this block's header rule —
568+
# never `<0.18.2`.
569+
# Re-check when a mermaid release declares a katex range that admits
570+
# 0.18.2: the entry then turns into a dedupe and stays as the floor.
571+
'katex@>=0.11.0 <0.19.0': '^0.18.2'

0 commit comments

Comments
 (0)