Repository navigation
fix(cli): extend the #8663 loader denylist and harden its scrub lifecycle #8763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
92c525f
eaac7ba
abee0fc
e34df6d
46e2690
ade3833
b77fc00
eca8ad2
3b70728
146c448
28352d5
02fcc3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
… surface The refcounted acquireInheritedLoaderEnvScrub read/wrote process.env from config/shared-env-keys.ts, which the serve process.env guard does not scan — moving the access out of run-qwen-serve.ts dropped its allowlisted count and failed process-env-guard.test.ts. Pass the env into the coordinator instead so run-qwen-serve.ts still owns the process.env reference (matching the existing scrub helpers), and update the allowlist to the new count.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -281,25 +281,29 @@ export interface InheritedLoaderEnvScrubHandle { | |
| release(): void; | ||
| } | ||
|
|
||
| // Scrubs loader vars from the live `process.env`, reference-counted so it is | ||
| // safe to call from overlapping daemon instances in one process. Use this at | ||
| // process-env boundaries; `scrubAndReportInheritedLoaderEnv` remains for | ||
| // one-shot scrubs of a private env object (ACP child / channel worker boot). | ||
| // Scrubs loader vars from a shared, live env (the daemon passes its own | ||
| // `process.env`), reference-counted so it is safe to call from overlapping | ||
| // daemon instances in one process. The caller owns the `process.env` | ||
| // reference so the serve-surface process.env guard still sees the access; | ||
| // `scrubAndReportInheritedLoaderEnv` remains for one-shot scrubs of a private | ||
| // env object (ACP child / channel worker boot). Concurrent callers must pass | ||
| // the same shared env object for the snapshot/restore refcount to be correct. | ||
| export function acquireInheritedLoaderEnvScrub( | ||
| env: NodeJS.ProcessEnv, | ||
| commandLabel: string, | ||
| processLabel: string, | ||
| ): InheritedLoaderEnvScrubHandle { | ||
| if (sharedProcessEnvScrubDepth === 0) { | ||
| sharedProcessEnvScrubOriginals.clear(); | ||
| for (const key of Object.keys(process.env)) { | ||
| for (const key of Object.keys(env)) { | ||
| if (!isLoaderEnvKey(key)) continue; | ||
| const value = process.env[key]; | ||
| const value = env[key]; | ||
| if (value !== undefined) sharedProcessEnvScrubOriginals.set(key, value); | ||
| } | ||
| } | ||
| sharedProcessEnvScrubDepth++; | ||
| const removedKeys = scrubAndReportInheritedLoaderEnv( | ||
| process.env, | ||
| env, | ||
|
Comment on lines
+398
to
+407
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] R1-2: A nested scrub acquisition deletes a later host assignment without snapshotting it. — Failure scenario: daemon A acquires, the embedding host assigns 中文说明R1-2: 嵌套 scrub acquire 会删除后续 host 赋值,却没有把它记入快照。失败场景:daemon A acquire 后,嵌入宿主设置 — gpt-5.6-sol via Qwen Code /review (v0.21.8) |
||
| commandLabel, | ||
| processLabel, | ||
| ); | ||
|
|
@@ -313,7 +317,7 @@ export function acquireInheritedLoaderEnvScrub( | |
| if (sharedProcessEnvScrubDepth > 0) return; | ||
| for (const [key, value] of sharedProcessEnvScrubOriginals) { | ||
|
Comment on lines
+419
to
+420
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] Mutant-survived: deleting the 中文说明变体存活:删除 release 时的 — deepseek-v4-flash via Qwen Code /review (v0.21.8) |
||
| // A later legitimate assignment wins over the restore. | ||
| if (!Object.hasOwn(process.env, key)) process.env[key] = value; | ||
| if (!Object.hasOwn(env, key)) env[key] = value; | ||
| } | ||
| sharedProcessEnvScrubOriginals.clear(); | ||
|
Comment on lines
+422
to
+424
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deferred to a follow-up. Valid surviving mutant with the same masking chain as the acquire-time clear; the shared two-cycle acquire/release test covers both and will land in the follow-up round. 中文说明延迟到下一轮。存活变异体属实,掩盖链与 acquire 时的 clear 相同;共用的双周期 acquire/release 测试同时覆盖两者,将在下一轮合入。 |
||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2141,7 +2141,11 @@ async function runQwenServeImpl( | |
| // process do not restore each other's loader vars mid-flight, and reverted | ||
| // on close() so an embedded caller reusing the host process gets its launch | ||
| // environment back. | ||
| const loaderEnvScrub = acquireInheritedLoaderEnvScrub('qwen serve', 'daemon'); | ||
| const loaderEnvScrub = acquireInheritedLoaderEnvScrub( | ||
| process.env, | ||
| 'qwen serve', | ||
| 'daemon', | ||
| ); | ||
| const scrubbedLoaderEnvKeys = loaderEnvScrub.removedKeys; | ||
|
Comment on lines
+2148
to
+2153
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declined this round (recorded, not dropped): the finding is diagnostics-only — reject/restore behavior itself is correct and test-pinned, as the finding notes. Durably logging the coordination state when a handle joins an already-active scrub, and surfacing the depth-0 restore through the callback channel before 中文说明本轮已记录并拒绝(非静默丢弃):该发现仅影响诊断——正如发现本身所述,拒绝/恢复行为是正确的,且有测试钉住。在 handle 加入已激活的剥离时持久记录协调状态、并在 |
||
| const restoreScrubbedLoaderEnv = (): void => { | ||
| loaderEnvScrub.release(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deferred to a follow-up. Valid surviving mutant: no test pins when the undefined-guard must not fire. The negative case (an explicitly
undefinedloader key is neither snapshotted nor restored) shares its setup with the two-cycle acquire/release test and will land with it.中文说明
延迟到下一轮。存活变异体属实:没有测试钉住 undefined 守卫"不应触发"的情形。负例(显式为
undefined的 loader 键既不被快照也不被恢复)与双周期 acquire/release 测试共用 setup,将与其一起合入。