Repository navigation
fix(deps): take the fix for next GHSA-vcvr-r3jv-pc5j (critical) and dompurify GHSA-p98j-92pf-mc4p - #21083
Conversation
…SA-p98j-92pf-mc4p OSV-Scanner on main's lockfile flags two rows: next 16.3.3 (CVSS 9.5, fixed 16.3.6) and dompurify 3.4.13 (CVSS 2.3, fixed 3.4.16). - apps/docs/package.json: the direct next pin moves 16.3.3 -> 16.3.6. - pnpm-workspace.yaml: the existing dompurify override's target lifts ^3.4.13 -> ^3.4.16, selector unchanged at the 4.0.0 boundary; its advisory-history comment is extended in place. - pnpm-lock.yaml: regenerated with pnpm 10.31.0 --lockfile-only. Only next, its nine @next/* packages and dompurify change version; the locked package count stays 1369. No osv-scanner.toml exemption. Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #21055 (body, triage ① Derived judgmentsDiff: 3 files, +80 −71 —
② Semver levelNothing published moves. ③ Boundary flags
No flag is left open. The PR is a draft on an Implemented-by: VERDICT: PASS |
… better-auth family (objectstack-ai#21094) (objectstack-ai#21162) Fixes objectstack-ai#21094 Clause-②: no Takes the 2026-10 production-dependency group that Dependabot opened as objectstack-ai#21029 (closed in favour of this card), without the better-auth family and without `next`. Maintainer ruling, verbatim: > 按你的推荐:关掉21029立卡,better-auth先放着,21024授权你落地 ## What lands - **43 manifests, 64 range moves.** The 63 range moves objectstack-ai#21029 made (diffed from its merge base `9b0de7de73` to its head `c0b7dd923e`) were re-applied one line at a time onto current `main`. The 64th is the `tsx` devDependency objectstack-ai#21160 added to `packages/drivers/driver-turso/package.json`, lifted from `^4.23.12` to `^4.23.15` after objectstack-ai#21160 was merged in. Each move matched the exact old spelling or the script refused. Excluded: `apps/docs/package.json` (`next` belongs to objectstack-ai#21055 / objectstack-ai#21083) and the five better-auth family lines in `packages/plugins/plugin-auth/package.json`, which stay at `1.7.3`. `pnpm-workspace.yaml` is not touched. Check, taken before the objectstack-ai#21160 merge: the sorted `-`/`+` lines of this branch's manifest diff equal objectstack-ai#21029's lines minus those exclusions (`diff` exit 0, 126 lines). - **`pnpm-lock.yaml`**, regenerated with the tooling in three steps (pnpm 10.31.0, the `packageManager` pin), never by hand: 1. `pnpm install --lockfile-only`, starting from main's lockfile. 2. `pnpm --filter @objectstack/plugin-hono-server --filter @objectstack/plugin-auth --filter @objectstack/hono update --lockfile-only --no-save hono`. Step 1 left `hono` at 4.13.7, below the `^4.13.9` that `plugin-hono-server` now publishes. The workspace override for `hono` (selector below 5.0.0) rewrites every declaration to `^4.13.5`, which 4.13.7 still satisfies, so lockfile inertia kept the old version. CI would have certified 4.13.7 while a downstream install gets 4.13.12. That is the declared-versus-tested split the card names for better-auth. Step 2 moves the single `hono` copy to 4.13.12 without editing the override or any manifest. An unfiltered `pnpm update -r` was tried and discarded: it also dropped `knex`'s `mysql2` / `pg` / `tedious` peer links in two importers. 3. After objectstack-ai#21160 landed: merge `main` (`e35c40a52`), lift driver-turso's new `tsx` line, and run `pnpm install --lockfile-only` again. - The result is a fixed point: a second `pnpm install --lockfile-only` leaves it byte-identical, and `pnpm install --frozen-lockfile` passes. Lockfile blob `30ba2147`. The resolved set is unchanged from the set the OSV scan below covered: 0 names differ. - **`packages/drivers/driver-turso/src/**`**: the item-4 restamp, 21 lines in 7 files (below). - **`packages/spec/src/data/driver/common.zod.ts` and `driver-credential-refusal.test.ts`**: the `@libsql/core` version label is restamped from 0.17.4 to 0.18.0. The TSDoc of `CREDENTIAL_URL_QUERY_PARAMS` says it was measured "in the versions pinned by this tree", so leaving 0.17.4 would have made it false. The behaviour was re-measured identical on the installed 0.18.0: `?authToken=` overrides the config token, `auth%54oken` is decoded, `AuthToken` and `token` give `URL_PARAM_NOT_SUPPORTED`, and the control without a query keeps the config token. - **`.changeset/21094-prod-deps-group.md`**: `patch` for the 19 published packages whose `dependencies` range moves. The list was re-derived from this diff and matches the PM correction on the card, `plugin-auth` included (`@noble/hashes`, `jose`). ## Resolved versions against the merge base Every changed `name@version` pair in the `packages:` section, compared with `main` at `e35c40a52`: 25 names change. **DOWN: 0.** | package | merge base | this branch | |:--|:--|:--| | `@libsql/client` / `@libsql/core` | 0.17.4 | 0.18.0 | | `zod` | 4.6.1 | 4.6.5 (4.6.1 kept by `apps/docs` only) | | `@modelcontextprotocol/sdk` | 1.30.0 | 1.31.0 | | `hono` | 4.13.7 | 4.13.12 | | `mongodb` | 7.5.0 | 7.7.0 (7.5.0 kept by `mongodb-memory-server-core` only) | | `jose` | 6.2.7, 6.2.8 | 6.2.12 | | `@noble/hashes` | 2.3.0 | 2.4.0 | | `@noble/ciphers` | 2.3.0 | 2.4.0 (2.3.0 kept by better-auth 1.7.3 only) | | `react` / `react-dom` / `@types/react` / `@types/react-dom` | 19.2.x | 19.3.0 (19.2.x kept by `apps/docs` only) | | `tsx` | 4.23.12 | 4.23.15 | | `yaml` | 2.9.0 | 2.9.1 (2.9.0 kept by the `apps/docs` fumadocs tree only) | | `chalk` | 6.0.0 | 6.0.1 | | `sql.js` | 1.14.1 | 1.14.2 | | `pinyin-pro` | 3.29.1 | 3.29.4 | | deduped onto a newer copy already present | `@hono/node-server` 2.0.12, `ws` 8.21.1, `@types/ws` 8.18.1, `eventsource-parser` 3.1.0 | removed (2.1.1, 8.22.0, 8.18.2, 3.1.1 stay) | | new transitive copies beside the old ones | none | `bson` 7.3.3 and `@mongodb-js/saslprep` 1.5.5 (with `mongodb` 7.7.0), `scheduler` 0.28.0 (with `react-dom` 19.3.0) | `nodemailer` stays at **10.0.13**, main's version and at least the required 10.0.12. Dependabot's regeneration had moved it down to 10.0.11. ## Item 4: `@libsql/client` lifted to `^0.18.0`, because the premise holds The premise was measured before any driver edit, three ways. 1. **Package diff.** `npm pack` of both releases. `@libsql/core` 0.17.4 and 0.18.0 differ only in `package.json` (the version). `@libsql/client` differs only in `lib-esm/sqlite3.js`, `lib-cjs/sqlite3.js`, `lib-esm/sqlite3.d.ts` and `package.json`. The change is a connection pool for the local `file:` client. `http.js`, `ws.js` and `node.js` are byte-identical. Installed side by side, `@libsql/hrana-client` 0.10.0 and native `libsql` 0.5.29 (with `@libsql/linux-x64-gnu`) are byte-identical too. 2. **Executed probe, same script against both installs.** Output is identical except for the version strings and one count: `syncUrl` occurrences in `sqlite3.js` go from 3 to 4 (the new pool-size line). 3. **The driver's own suite.** At base with 0.17.4: 81 files, 2210 passed, 33 skipped. With 0.18.0, before the restamp: 2209 passed, 1 failed, 33 skipped. Per-test outcomes are identical except the version pin (`expected '0.18.0' to be '0.17.4'`). After the restamp: 2210 passed, 33 skipped. At `0f87e8488`, with objectstack-ai#21160's tests merged in: 2218 passed, 33 skipped, 0 failed. | site (at base) | claim | 0.18.0 reading | verdict | |:--|:--|:--|:--| | `turso-authtoken-url-channel.test.ts:17-18` | client / core / native versions, range | client 0.18.0, core 0.18.0, native `libsql` 0.5.29; range now `^0.18.0`. Answers 1-4 (live wire, child-process replica endpoint) pass, 7/7 non-pin cases, as 8/8 did on 0.17.4 | held, restamped | | `turso-authtoken-url-channel.test.ts:281` | version pin | `0.18.0` | pin moved | | `turso-driver-remote-url-replica-refusal.test.ts:28`, `turso-driver.ts:1288`, `:1384` (message) | no embedded replica for a remote url | `syncUrl` lines: `http.js` 0, `ws.js` 0, control `authToken` lines 6 / 6. `https` and `ws` clients' `sync()` reject `SYNC_NOT_SUPPORTED`. `:memory:` + `syncUrl` throws `URL_INVALID` ("Embedded replica must use file for local db"). File 27/27 on both versions | held | | `turso-driver-timeout.test.ts:9`, `turso-driver.ts:152` | HTTP arm rides `Config.fetch`; replica `sync()` is native | `http.js` (one `config.fetch` site) and hrana-client byte-identical. Timeout file 5/5, supplied-client refusal file 13/13 on both | held | | `turso-driver.ts:871` | `Config.timeout` is the busy timeout; "remote clients ignore it" | core `api.d.ts` docblock byte-identical | held | | `turso-driver-unrecognised-url-refusal.test.ts:26`, `turso-driver.ts:1313`, `:1417` (message) | refusals of urls the client rejects | `URL_INVALID` for `./data/app.db`, `data/app.db`, `/abs/app.db`, `:MEMORY:`, empty, `libsql:host` (bare paths "not in a valid format"). `URL_SCHEME_NOT_SUPPORTED` for `sqlite:`, `memory://`, `C:\data\app.db`. File 42/42 on both | held | | `turso-driver-uppercase-ws-scheme-timeout-refusal.test.ts:15`, `:26`, `turso-driver.ts:932` | `expandConfig` lowercases the scheme before the switch | `WSS://…` gives `wss`, `Ws://…` gives `ws`, control `LIBSQL://…` gives `https`. `_createClient(expandConfig(config, true))` present (1 hit). File 20/20 on both | held | | `turso-driver-ws-timeout-refusal.test.ts:10`, `turso-driver.ts:963`, `:1001` (message) | the WS client takes no `fetch` and no timeout | `ws.js`: `fetch` 0, `timeout` 0. hrana `ws/*.js` + `index.js` `timeout` 0, control `fetch` over `http/*.js` 15. File 11/11 on both | held | | `turso-driver.ts:1061` (message) | a built client's transport cannot be re-seamed | `config.fetch` is read once, inside `_createClient` in `http.js` (byte-identical) | held | | `turso-driver.ts:1212` | the client folds scheme case and opens each spelling | `FILE:./x.db` gives `file`, `Wss://` gives `wss`, `LIBSQL://` gives `https`. `createClient` opens each (`http` / `ws` / `file`) | held | | `turso-driver.ts:1244` | `:memory:` expands to `file::memory:`; `isInMemoryConfig` | `file::memory:`. `true` for `file::memory:` and `file::memory:?cache=shared`, control `false` for `file:./x.db` | held | After the edit, `git grep -n -E "0\.17\.[0-9]" -- packages/drivers/driver-turso/src` returns 0 lines (exit 1). The control is the 23 `0.18.0` occurrences in the same 7 files. ## What objectstack-ai#21029 never measured - **Test Core shard 4's eight unreached packages**, measured at `cf1d700b`, before the `main` merge: `rest` 250 files, 4728 passed / 248 skipped. `driver-sql` 205 files, 3303 passed / 188 skipped. `plugin-email` 31 files, 510 passed. `plugin-approvals` 52 files, 804 passed. `plugin-webhooks` 13 files, 160 passed. `trigger-schedule` 8 files, 170 passed. `connector-mcp` 3 files, 23 passed. `client-react` 3 files, 34 passed. Turbo ran 45 of 45 tasks, exit 0. - **`Lint & Repo Gates` from `check:vendor-export-contract` on**: `pnpm check:vendor-export-contract` reads `VERDICT: PASS — vendor export contract (installed workspace), 1 edge(s) verified` (better-auth 1.7.3), and the `-resolve` variant passes on the registry. The 72 later steps of that job were not run here. They belong to CI's run on this PR. The families this diff derives are below. - **OSV.** `osv-scanner` v2.3.8, built from the Go module proxy because this container's egress refuses `api.osv.dev`. It ran on the offline npm database over lockfile blob `70547c67` (its resolved set is identical to the current `30ba2147`), with the repo's `osv-scanner.toml` loaded: 1388 packages, `No issues found`, exit 0. Positive control: the same lockfile with `hono` rewritten to 4.12.32 gives exit 1 and 8 advisories on `hono`, among them GHSA-8j4g-w8fx-2239. CI's online step is the authoritative reading. - **`zod` 4.6.5 and `z.properties()`**: `git grep -n -E "z\.properties\(" -- packages/` returns 0 lines; control `z.object(`, 1825 lines. - **`mongodb` live suites**: NOT MEASURED. They need a `mongod` download from `fastdl.mongodb.org`, which this container's egress refuses (CONNECT 403). The default `driver-mongodb` suite passes: 30 files, 675 passed, 172 skipped (the five opt-in live files). ## Gates and tests Gate families derived by `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (no paths, change set from git) at HEAD **`0f87e8488`** (54 paths against merge base `e35c40a52`): 117 commands. All 117 exit 0, and so does `pnpm check:vendor-export-contract`. Exit codes were captured before any pipe. `--ran` reconciliation: `117 derived, 117 run, 0 NOT-MEASURED, 0 UNRUN`, a derived zero with an exit code on every line. Package suites, all exit 0: - At `cf1d700b`: `driver-mongodb`, `mcp` 32/344, `plugin-hono-server` 27/324, `plugin-auth` 115/2472, `service-settings` 33/584, `plugin-pinyin-search` 2/21, `driver-sqlite-wasm` 36/675, `driver-memory` 69/1613, `service-analytics` 155/3526 (10 skipped), `create-objectstack` 16/247, `@objectstack/hono` 5/122. Also `@objectstack/cli` `--project unit` 242/3432 and `@objectstack/spec` `--project local` 591 files / 17368 passed. - `typecheck`: the 19 moving packages plus `client-react`, `@objectstack/hono` and `lint`. Turbo ran 80 of 80 tasks. - At `0f87e8488`, after the objectstack-ai#21160 merge and a full rebuild: the `driver-turso` suite (82 files) gives 2218 passed / 33 skipped / 0 failed. That includes objectstack-ai#21160's new tests, run on 0.18.0; its two-process concurrency test overlapped, with 400 writes and 400 distinct numbers. `typecheck` passes, and `pnpm install --frozen-lockfile` passes. ## Acceptance notes - **Duplicate copies left by the exclusions**: `zod` 4.6.1, `react` 19.2.8 and `yaml` 2.9.0 are kept only by the excluded `apps/docs` tree. `@noble/ciphers` 2.3.0 is kept only by the excluded better-auth 1.7.3. `mongodb` 7.5.0 is kept only by the test harness `mongodb-memory-server-core` 11.3.0. - **libsql 0.18.0's one behaviour change, from reading the code (not measured):** the local client now pools connections, with one connection for `:memory:` and for embedded replicas. On a replica, a second `sync()` therefore waits for the first to release the connection. On 0.17.4 the two ran at once on the same native handle. With `timeout` set, a sync that outlives the window keeps running natively, uncancelled, so the next periodic sync queues behind it. No driver docblock claims either behaviour. - **The remaining 0.17.4 stamps stay**: outside `CHANGELOG.md`, only `service-package` `index.ts:192` and `mysql2-tuple.test.ts:172` name 0.17.4 ("Measured on `@libsql/client` 0.17.4"). That is a dated attestation and stays true; the `result.rows` shape was re-measured identical on 0.18.0. - **Environment side effect, nothing committed**: turbo 2.11.5 appends a managed block to `AGENTS.md` whenever an agent runs a repository-scoped turbo command. It was restored after each turbo run with `git restore --source=HEAD --staged --worktree AGENTS.md`. No commit on this branch touches `AGENTS.md`. - **Merge-queue ejection and its fix**: objectstack-ai#21160 added driver-turso's `tsx` at 4.23.12 while this branch removes `tsx@4.23.12`. The two lockfiles merged into one that `pnpm install --frozen-lockfile` refuses. Fixed by merging `main` at `e35c40a52`, lifting that `tsx` line, and regenerating the lockfile with pnpm. --- _Generated by [Claude Code](https://claude.ai/code/session_018gA1pE6eJtwHhqx72G8U9X)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #21055
Clause-②: no
Summary
Validate Package Dependenciesruns OSV-Scanner againstpnpm-lock.yaml. Onmainit flags two rows, so the scheduled scan is red, and so is every PR that touches apackage.json:nextdompurifyBoth advisories name a fixed version, so this PR takes the fix.
osv-scanner.tomlis untouched and still holds zero exemptions.Change
apps/docs/package.json: the directnextpin moves from16.3.3to16.3.6. The pin stays exact, as it was. 16.3.6 is the advisory's fixed version and the same target as Dependabot's grouped chore(deps)(deps): bump the production-dependencies group with 27 updates #21029, so after this lands, that PR'snextline is already satisfied rather than in conflict. The newer patches (16.3.7, 16.3.8) are left to the Dependabot group. No workspace manifest declareseslint-config-nextor any@next/*package. The nine@next/*packages in the lockfile arenext's own dependencies and move with it.pnpm-workspace.yaml: the existingdompurifyoverride's target goes from^3.4.13to^3.4.16. Its selector is unchanged, still bounded at the 4.0.0 major. The OSV comment above it is extended in place, in the style of its neighbours. This PR adds no second override and does not touch the rootpackage.json.pnpm-lock.yaml: regenerated, not hand-edited (see below).Correction to the issue body. The issue says the root
pnpm.overrideshas no floor fordompurify. Onmain, the workspace's overrides live inpnpm-workspace.yaml, because pnpm 10 ignorespnpm.overridesinpackage.json. Adompurifyentry was already there at^3.4.13, added for an earlier advisory (#6407). The new advisory's range is introduced 3.4.13, fixed 3.4.16, so the old floor was itself the first affected version. The existing comment had predicted this: it explains that the selector is bounded at the major so that a target-only lift is all a case like this needs.mermaid@11.16.1declaresdompurify ^3.3.3, which admits 3.4.16, so this is a dedupe onto the patched line and does not force an upgrade past whatmermaidsupports.Reach.
apps/docs/app/og/docs/[...slug]/route.tsximportsImageResponsefromnext/og. That is the surface GHSA-vcvr-r3jv-pc5j names ("Remote Code Execution in next/og ImageResponse").Lockfile
Regenerated with
pnpm install --lockfile-onlyunder pnpm 10.31.0, thepackageManagerversion.next,@next/env, the eight@next/swc-*binaries, anddompurify.nextversion. They belong tobetter-auth, its three@better-auth/*plugins, andfumadocs-core/fumadocs-mdx/fumadocs-ui. None of those packages changes version.pnpm install --frozen-lockfilepasses on the result.OSV-Scanner, before and after
I ran OSV-Scanner v2.3.8, the version the workflow's action pins. The binary's SHA-256 (
bc98e153…) matches the release's checksum file. The command wasscan --offline-vulnerabilities --lockfile=pnpm-lock.yaml. The container's egress proxy refusesapi.osv.dev, so the scan reads the offline npm database the scanner downloads, the same method as #20774.mainat5dbeb7d7b768c26aa189No issues found(1369 packages)Changeset decision
No changeset; this PR should carry the
skip-changesetlabel. Nothing it touches is published:apps/docsis"private": true.pnpm-workspace.yamloverrides andpnpm-lock.yamlare in no package'sfiles[], and no published manifest changes.check:override-consistencystill reports its 9 published-manifest declarations covered, andcheck:published-filesis green.What I ran
The final head is
68c26aa189: my commit, then a merge ofmainat0c5a71b094. Every row below was measured on that head. The build and the docs checks were also green on3714ec8cef, before the merge.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands68c26aa189after a rebuild, codes recorded with the--ranidiomdispatch-gates --ran41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUNpnpm buildunder the shared verify lock,--concurrency=23714ec8cefand at68c26aa189pnpm --filter @objectstack/docs typecheck(fumadocs-mdx && next typegen && tsc --noEmit)apps/docs/vercel.json):pnpm turbo run build --filter=@objectstack/docsNext.js 16.3.6,.next/BUILD_IDwritten, and the docs task was a cache miss, so it really executedcheck:override-consistency,check:vendor-export-contract-resolve,check-osv-exemptions,check:nul-bytes,check:workspace-manifest-cyclesOne deliberate difference from CI: the docs build ran without CI's
TURBO_FORCE, which would also re-execute thespecbuild. The docs task itself missed the cache and ran. No package test suite applies, because no package source changes. CI's shard, dogfood and workspace type-check lanes are left to CI.Acceptance notes
dompurifyoverride lives, applies to the issue body only. It does not affect the remedy.nextline is already satisfied, and Dependabot will rebase its lockfile.Generated by Claude Code