Skip to content

Commit b93c750

Browse files
fix(deps): re-lock vitest and the @vitest/* family onto 4.1.12 for the two @vitest/mocker OSV advisories (#25164)
Fixes #25163 Clause-②: no ## What this does `main`'s scheduled `Validate Dependencies` run 39714768704 (job 119614140669, `main` at `6b44efa7b4`) is red at its OSV step on two Medium advisories in `@vitest/mocker` 4.1.11, and both name 4.1.12 as the fix. 4.1.12 is the newest 4.1.x on npm (published 2026-10-15). Every declared range on every path already admits it, so this is a **re-lock only**. `pnpm-lock.yaml` is the whole diff: no override, no `osv-scanner.toml` exemption, and no `package.json` range. `vitest` 5.x is not touched. | Package | Locked → resolved | Advisories | Path (`pnpm why -r`) | How | |:--|:--|:--|:--|:--| | `@vitest/mocker` | 4.1.11 → **4.1.12** | GHSA-qxg6-89mg-rqv8 (CVSS 4.7), GHSA-xp26-3454-mjgp (CVSS 5.9) | exact dependency `4.1.11` of `vitest@4.1.11`, 2 peer variations | re-lock | | `vitest` | 4.1.11 → **4.1.12** | (carries the mocker) | direct devDependency `^4.1.11` in 79 importers: 78 under one peer variation, `@objectstack/account` under the other. Also the optional peer `^2.0.0 \|\| ^3.0.0 \|\| ^4.0.0 \|\| ^5.0.0` of `better-auth`, `@better-auth/oauth-provider`, `@better-auth/scim` and `@better-auth/sso` 1.7.12 | re-lock | | `@vitest/coverage-v8` | 4.1.11 → **4.1.12** | none (peers `vitest` exactly, so it moves with it) | direct devDependency `^4.1.11` in `@objectstack/spec` | re-lock | | `@vitest/expect`, `@vitest/pretty-format`, `@vitest/runner`, `@vitest/snapshot`, `@vitest/spy`, `@vitest/utils` | 4.1.11 → **4.1.12** | none (lockstep) | exact dependencies `4.1.11` of `vitest@4.1.11` | re-lock | No `@vitest/ui` or any other `@vitest/*` package is in the lockfile. **The two `~4.0.0` declarations** are both in `packages/create-objectstack/src/templates/blank/package.json` (`devDependencies.vitest` and `overrides.vitest`). That file is a scaffold template, not a workspace importer: it matches no `pnpm-workspace.yaml` glob, the lockfile has no importer for it, and no 4.0.x `vitest` / `@vitest/*` entry is in the lockfile. They are left alone. What they resolve to in a scaffolded project is in Acceptance notes. ## The advisories, read from the OSV npm database `api.osv.dev`, `api.github.com/advisories` and the `github.com/advisories` pages all answer 403 from this container. The two records were read instead from the OSV npm database archive (`osv-vulnerabilities.storage.googleapis.com/npm/all.zip`, fetched 2026-10-22 03:17 UTC): - **GHSA-qxg6-89mg-rqv8**, "Vitest: Code injection via unauthenticated manual mock registration". `interceptorPlugin` accepts `vitest:interceptor:register` events on Vite's dev-server WebSocket without authentication, and `createManualModuleSource` interpolates the mock's URL into generated module source without escaping. Affected: from 2.1.0-beta.7 up to the fix in 4.1.12, and from 5.0.0-beta.1 up to the fix in 5.0.3. - **GHSA-xp26-3454-mjgp**, "Windows backslash traversal bypasses the @vitest/mocker redirect allowlist fix". This is a bypass of GHSA-82fw-gwwq-j7x9's fix. Affected: exactly 4.1.11, and from 5.0.0-rc.2 up to the fix in 5.0.3. **What 4.1.12 changes.** I diffed the published 4.1.11 and 4.1.12 tarballs of all nine family members: - The only behavioural code change is the two fixes in `@vitest/mocker`'s `dist`. `createManualModuleSource` now uses `JSON.stringify` for the URL and the export names, and the redirect join now applies a backslash-to-slash `slash()` to the pathname. - `vitest` changes only its version string and two chunk-hash renames. - `@vitest/coverage-v8` changes only its version string. - `runner`, `expect`, `snapshot`, `spy`, `utils` and `pretty-format` have 0 non-manifest diff lines. - In the manifests, the only change other than the self-version is one optional peer of `vitest`: `@vitest/browser-webdriverio` goes from `4.1.11` to `^4.1.11`. That is the self-contradictory peer `d795719926` measured against npm 10. It is optional and not installed in this workspace, and pnpm prints no warning for it. ## How the lockfile was moved, and the route rejected first - **Rejected: a targeted `pnpm update`.** I measured `pnpm update -r --no-save vitest @vitest/coverage-v8`. It did reach 4.1.12 for all nine members and moved no `package.json`. It also touched 29 package names outside the family in `packages:` (24 replaced, 5 added), at +317/−284 lines: - `@inquirer/ansi` / `confirm` / `core` / `type`, `seroval` 1.6.8 → 1.7.0, `seroval-plugins` 1.6.8 → 1.6.12, and `chai` 6.2.2 → 6.3.0; - `rolldown` and its 15 bindings 1.2.14 → 1.2.15, and `@oxc-project/types` 0.154.0 → 0.155.0; - new copies of `@babel/runtime`, `ip-address`, `nanoid`, `postcss` and `set-cookie-parser`; - in `snapshots:`, rewritten `knex`, `tsup`, `postcss-load-config` and `fumadocs-mdx` keys, and changed bodies on 7 same-key snapshots (`@tanstack/router-core`, `@testing-library/dom`, `headers-polyfill`, `msw`, `socks` and both `vite` 8.3.4 variations). - This is the same churn #25047 measured for `pnpm update` in this workspace, plus the `rolldown`, `@oxc-project/types` and `chai` moves. - **Taken: the re-lock recipe of #21951 / #25047.** - I added two temporary exact entries (`vitest: '4.1.12'`, `'@vitest/coverage-v8': '4.1.12'`) to the `overrides` block of `pnpm-workspace.yaml`, under an EXIT trap that restores the file, and ran `pnpm install`. - I then restored the file and ran `pnpm install` again. The second install keeps the resolutions, because every declared range admits them. - The restore is proven: `git hash-object pnpm-workspace.yaml` equals the HEAD blob `d9b99fcddf13011318845269277987410889b7c0`, and `git diff HEAD -- pnpm-workspace.yaml` is empty. ## Lockfile diff scope `pnpm-lock.yaml` only, **+159/−159**. I compared the parsed lockfiles, base `6b44efa7b4` against head `9ada86315f`: - **`packages:`** 1340 → 1340 keys: 9 removed, 9 added, which are exactly the nine family members 4.1.11 → 4.1.12. No same-key entry changed. - **`snapshots:`** 1347 → 1347 keys: 15 removed, 15 added. - 11 are the family. `vitest` and `@vitest/mocker` each have two peer variations, which differ only in `vite`'s `esbuild` 0.28.1 / 0.28.2 peer. - 4 are `better-auth`, `@better-auth/oauth-provider`, `@better-auth/scim` and `@better-auth/sso` 1.7.12. They rewrite only their `vitest` peer suffix: `better-auth` 1.7.12 declares `vitest` as an optional peer, and pnpm binds it to the workspace's copy. - No same-key entry changed. - **`importers:`** 85 → 85, 0 specifier moves. - 79 `vitest` and 1 `@vitest/coverage-v8` version strings move to 4.1.12. - The 4 `better-auth` version strings in `@objectstack/plugin-auth` change only their peer suffix. - **Unchanged:** `lockfileVersion` (9.0), `settings`, `overrides` and `patchedDependencies`. - Nothing outside the family moved, apart from the four peer-suffix rewrites; `chai` stays at 6.2.2. ## Local proofs, at `9ada86315f` | Proof | Exit | Reading | |:--|:--|:--| | `pnpm install --frozen-lockfile --prefer-offline` (the workflow's lockfile step) | 0 | | | `node scripts/check-changeset-fixed.mjs` | 0 | `"fixed" group is in sync with 73 public workspace packages` | | `pnpm check:override-consistency` (the published-manifest override check) | 0 | `9 published-manifest declaration(s) covered by pnpm-workspace.yaml overrides all resolve to their override targets` | | `pnpm check:vendor-export-contract-resolve` | 0 | `VERDICT: PASS — vendor export contract (registry resolution, installed with npm@11.21.0), 3 edge(s) verified` | | `node scripts/check-osv-exemptions.mjs --self-test` and the bare run | 0, 0 | `1 OSV exemption(s) … all carry an unexpired ignoreUntil within 90 days and a reason with an advisory link` | | `node scripts/osv-base-relative.mjs --self-test` | 0 | `23 case(s), all held (floor 23)` | | `pnpm --filter @objectstack/spec build` (shared verify lock) | 0 | `VERDICT command-exit 0` | | `pnpm --filter @objectstack/formula test` (shared verify lock) | 0 | `RUN v4.1.12`, 51 files / 1367 tests passed. Includes `src/cel-env-reuse.test.ts`, which module-mocks `@marcbachmann/cel-js` with `vi.mock(…, async (importOriginal) =>)`: `@vitest/mocker`'s path. Resolved from the package: `vitest` 4.1.12, `@vitest/mocker` 4.1.12 | | `pnpm --filter @objectstack/types test` (shared verify lock) | 0 | `RUN v4.1.12`, 29 files / 774 tests passed | | `@objectstack/spec`'s six `vi.mock` test files with `--coverage` (provider v8, shared verify lock) | 0 | `RUN v4.1.12`, `Coverage enabled with v8`, 6 files / 101 tests passed. This loads `@vitest/coverage-v8` 4.1.12 against its exact `vitest` 4.1.12 peer | `pnpm install` prints `ioredis-mock 8.13.1: unmet peer ioredis@^5: found 6.0.0`. That warning is already on `main` and is not caused by this diff. ## OSV reading I measured with OSV-Scanner **2.5.0**, the binary the workflow's pinned action image ships. Its sha256 `edcfc41d…524e0c` matches the release's `SHA256SUMS`. `api.osv.dev` is refused by this container's egress proxy, so the scans ran offline (`--offline-vulnerabilities --download-offline-databases`) against the npm database downloaded 2026-10-22 03:24 UTC. Each side ran under its own `osv-scanner.toml`, with the identical invocation. - **Base `6b44efa7b4`: exit 1.** The 2 rows are the scheduled run's: 1340 packages, `@vitest/mocker` 4.1.11, fixed in 4.1.12, CVSS 4.7 and 5.9. The sprintf-js exemption is filtered. - **This PR `9ada86315f`: exit 0, `No issues found`.** The sprintf-js exemption is filtered here too. That is the control that shows the database loaded and matched. - **The scheduled run's own invocation** (`--lockfile=pnpm-lock.yaml` from the worktree root, ledger auto-loaded): exit 0, `No issues found`, with `Loaded npm local db` and the exemption filtered. - **`scripts/osv-base-relative.mjs`** over both JSON results: exit 0, `0 introduced, 0 inherited, 2 resolved`. - **One void reading, declared:** my first run of the root invocation, without `--download-offline-databases`, printed `No issues found` at exit 0. It printed no `Loaded npm local db` line and no filtered exemption, so it had loaded no database. It is not counted. What closes the card's last clause is the next scheduled (or a `workflow_dispatch`) `Validate Dependencies` run on `main`. This PR's own run takes the base-relative path. ## Changeset: `skip-changeset`, measured Nothing publishes. - The diff is `pnpm-lock.yaml` alone. No `package.json` changed, so every published package's declared ranges are byte-identical, and a downstream install resolves exactly as before. - No manifest in the repository declares `vitest` or any `@vitest/*` package as a `dependency`, `peerDependency` or `optionalDependency` (0 hits over every tracked `package.json`). - No `tsup` config names `vitest` in `noExternal` (0 hits). - The built `@objectstack/spec` `dist` has 0 files naming `@vitest/` or `createManualModuleSource`. The positive control is 7 files in `@vitest/mocker` 4.1.12's own `dist`. - No `.changeset/*.md` file is touched. ## Gates - **Derivation.** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `9ada86315f` derived 19 commands from 1 path. I ran all 19, each exit captured before any pipe. - **`--ran` reconciliation:** `19 derived, 17 run, 2 NOT-MEASURED, 0 UNRUN`. - **17 exited 0:** - the `node` gates `check-changeset-fixed`, `check-closing-keyword-parity` (+ `--self-test`), `check-comment-mask-corpus`, `check-dts-emitted --self-test`, `check-osv-exemptions` (+ `--self-test`) and `osv-base-relative --self-test`; - the `pnpm` gates `check:driver-memory-census`, `check:dts-closure`, `check:gitlink-declared`, `check:nul-bytes`, `check:override-consistency`, `check:refd-timer-probe`, `check:sourcemap-no-sources-content`, `check:vendor-export-contract-resolve` and `check:watch-hint-literal`. - **Partial sweeps:** `check:dts-closure` and `check:sourcemap-no-sources-content` swept only the one built package, `@objectstack/spec`. - **NOT MEASURED:** `pnpm check:dual-build-cjs-loads` and `pnpm check:lean-entry-closure` each exit 3 (`PREREQUISITE NOT MET`, built output absent; both need a full `pnpm build`). CI's `Build Core` and `Lint & Repo Gates` measure them on the built tree. - **`git merge-tree --write-tree origin/main HEAD`** (`origin/main` = `06900c9c23`): exit 0, clean. `pnpm-lock.yaml` is not routed to the `os-regen` driver, so this local reading answers GitHub's question. The 1 commit `main` gained since the base touches none of `pnpm-lock.yaml`, `pnpm-workspace.yaml`, any `package.json` or `osv-scanner.toml`. ## Acceptance notes - **A scaffolded project still resolves an affected `@vitest/mocker`.** - `create-objectstack` copies `src/templates` into `dist/templates`, and `files` ships `dist`. So the blank template's `vitest: ~4.0.0`, held by its matching npm `overrides`, ships. - `~4.0.0` resolves to `vitest` 4.0.18 today, which depends on `@vitest/mocker` 4.0.18 exactly. That is inside GHSA-qxg6-89mg-rqv8's affected range, and the advisory names no 4.0.x fix. GHSA-xp26-3454-mjgp does not reach 4.0.x. - The pin is deliberate (`d795719926`): `vitest` 4.1.12's self-contradictory `@vitest/browser-webdriverio ^4.1.11` peer crashes npm 10's arborist with `edgesOut`. Lifting it is a trade-off and outside this card's file surface. - Reported to the seat in the dev report; not filed here. - Many comments and pins record behaviour "measured on vitest 4.1.11" (for example `packages/spec/vitest.config.ts`, `packages/cli/vitest.config.ts`, and the `@vitest/runner@4.1.11` `withTimeout` notes in `packages/client` tests). After this re-lock they name the previous patch. The tarball diff above shows `@vitest/runner` and the `vitest` CLI are byte-identical apart from the version string, so the recorded behaviour still holds on 4.1.12. CI's `Test Core` runs the suites that spawn a real vitest child to pin it. Class: none; carrier: none. - In this workspace, `pnpm update` re-resolves a fixed set of unrelated packages even when it is targeted. The temporary-override re-lock is the route that keeps a lockfile refresh narrow. Class: none (tooling behaviour, not a defect of this repo); carrier: none. - `git push` printed GitHub's notice of "3 vulnerabilities on the default branch (1 critical, 2 moderate)". The two moderate match this card. The OSV scan of `main` matches nothing else outside the exempted sprintf-js advisory. Dependabot alerts are not readable from this session (`Resource not accessible by integration`, 403), so the critical one is not identified here. Class: none; carrier: none. --- _Generated by [Claude Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent e3aa111 commit b93c750

1 file changed

Lines changed: 159 additions & 159 deletions

File tree

0 commit comments

Comments
 (0)