You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#11341 landed check:cli-test-child-env, which refuses a bulk process.env copy in a spawner file under packages/cli/test/**. The leaks that predate the gate are recorded in scripts/cli-test-child-env.baseline.json as a shrink-only ratchet. This card is the burn-down.
The gate deliberately did not repair them: sweeping without the mechanism leaves the next file free to reintroduce the shape (#11341's own argument), and two of the files below were held by #11071 in a parallel seat the round the gate landed.
The ledger, as it stands
18 bulk references across 17 files:
file
count
cloud-login-json-ndjson.e2e.test.ts
1
generate-agent-retired.e2e.test.ts
1
generate-skill.e2e.test.ts
1
hook-body-build-reach.e2e.test.ts
1
init-created-files-summary.e2e.test.ts
1
invocation-loudness.e2e.test.ts
1
json-stdout-purity.e2e.test.ts
1
login-json-ndjson.e2e.test.ts
1
login-json-noninteractive.e2e.test.ts
1
migrate-exit-code.e2e.test.ts
1
migrate-meta.e2e.test.ts
2
qa-empty-glob-exit-code.e2e.test.ts
1
serve-app-anchored-optional-import.e2e.test.ts
1
serve-app-runtime-hooks.e2e.test.ts
1
serve-host-fallback-base.e2e.test.ts
1
validate-json-warning-parity.e2e.test.ts
1
validate-top-level-strict.e2e.test.ts
1
node scripts/check-cli-test-child-env.mjs --list prints this live, with line numbers and the enclosing function, so no worklist has to be maintained by hand — the enumeration in this body is a snapshot and the command is the source of truth.
One card per neighbourhood, not one sweep
The repair is mechanical (env: childEnv({ ... }) in place of the spread) but it is not uniformly risk-free, which is why it is split rather than batched:
serve-app-anchored-optional-import.e2e.test.ts is the one that matters most. Its hand-rolled runServeFrom() boots a real os serve with the full stack — better-auth included — so it is the single file in the directory that has the leak and mounts something that reads TEST. It asserts optional-service resolution today, so nothing it checks can currently be softened into a pass, but its assertions are one edit away from being security-relevant. finding: #11341's bare-...process.env worklist is two files short, and one of them spawns a real os serve #11441 is the card that measured it.
The serve-* files each need the child re-checked after the strip: the crypto provider persists a minted key to $HOME/.objectstack/dev-crypto-key in development mode, which is why runServe() passes an explicit OS_SECRET_KEY. A file that stops claiming to be a vitest worker may need the same. helpers/serve-process.ts's header carries the measurement, and serve-node-env-production-default going red the moment the leak stopped is the recorded precedent for a pin whose "production posture" was genuine for auth and fake for crypto.
The remaining login / migrate / validate / init / qa / hook / json-stdout files spawn commands that mount nothing reading the runner family. Those are the cheap batch.
Ratchet mechanics for whoever takes a slice
Lower the count in scripts/cli-test-child-env.baseline.json in the same PR, and delete the key when it reaches 0 — the gate fails on a stale ceiling, in that direction too, deliberately: a ceiling left above reality silently licenses that many new leaks.
#11341 landed
check:cli-test-child-env, which refuses a bulkprocess.envcopy in a spawner file underpackages/cli/test/**. The leaks that predate the gate are recorded inscripts/cli-test-child-env.baseline.jsonas a shrink-only ratchet. This card is the burn-down.The gate deliberately did not repair them: sweeping without the mechanism leaves the next file free to reintroduce the shape (#11341's own argument), and two of the files below were held by #11071 in a parallel seat the round the gate landed.
The ledger, as it stands
18 bulk references across 17 files:
cloud-login-json-ndjson.e2e.test.tsgenerate-agent-retired.e2e.test.tsgenerate-skill.e2e.test.tshook-body-build-reach.e2e.test.tsinit-created-files-summary.e2e.test.tsinvocation-loudness.e2e.test.tsjson-stdout-purity.e2e.test.tslogin-json-ndjson.e2e.test.tslogin-json-noninteractive.e2e.test.tsmigrate-exit-code.e2e.test.tsmigrate-meta.e2e.test.tsqa-empty-glob-exit-code.e2e.test.tsserve-app-anchored-optional-import.e2e.test.tsserve-app-runtime-hooks.e2e.test.tsserve-host-fallback-base.e2e.test.tsvalidate-json-warning-parity.e2e.test.tsvalidate-top-level-strict.e2e.test.tsnode scripts/check-cli-test-child-env.mjs --listprints this live, with line numbers and the enclosing function, so no worklist has to be maintained by hand — the enumeration in this body is a snapshot and the command is the source of truth.One card per neighbourhood, not one sweep
The repair is mechanical (
env: childEnv({ ... })in place of the spread) but it is not uniformly risk-free, which is why it is split rather than batched:serve-app-anchored-optional-import.e2e.test.tsis the one that matters most. Its hand-rolledrunServeFrom()boots a realos servewith the full stack — better-auth included — so it is the single file in the directory that has the leak and mounts something that readsTEST. It asserts optional-service resolution today, so nothing it checks can currently be softened into a pass, but its assertions are one edit away from being security-relevant. finding: #11341's bare-...process.envworklist is two files short, and one of them spawns a realos serve#11441 is the card that measured it.serve-*files each need the child re-checked after the strip: the crypto provider persists a minted key to$HOME/.objectstack/dev-crypto-keyin development mode, which is whyrunServe()passes an explicitOS_SECRET_KEY. A file that stops claiming to be a vitest worker may need the same.helpers/serve-process.ts's header carries the measurement, andserve-node-env-production-defaultgoing red the moment the leak stopped is the recorded precedent for a pin whose "production posture" was genuine for auth and fake for crypto.generate-skill.e2e.test.tsandgenerate-agent-retired.e2e.test.tssit inos gwritesNAME.tsfor six generators while the type registry declaresNAME.TYPE.ts— #11025 closed it forskillalone #11071's neighbourhood — check it has landed before touching them.login/migrate/validate/init/qa/hook/json-stdoutfiles spawn commands that mount nothing reading the runner family. Those are the cheap batch.Ratchet mechanics for whoever takes a slice
Lower the count in
scripts/cli-test-child-env.baseline.jsonin the same PR, and delete the key when it reaches 0 — the gate fails on a stale ceiling, in that direction too, deliberately: a ceiling left above reality silently licenses that many new leaks.Related
packages/cli/testspawner from re-introducing the bare...process.envchild env #11341 — the gate, its rule, and the twoDELIBERATEsites that are not in this ledger....process.envworklist is two files short, and one of them spawns a realos serve#11441 — the measurement correction that named two of the files above.packages/cli/testspawners pass noenvat all, so the child inherits the vitest worker environment verbatim — the purer form of #11341's leak, and the new gate is silent on it #11595 — the sibling gap: 8 spawners that pass noenvat all. Not in this ledger; a different remedy.os serveunder vitest inheritTEST=true, which makes better-auth silently skip origin/CSRF validation regardless ofNODE_ENV#11267 — wherechildEnv()came from, and the measurement that says why it matters.