qwen-code/docs
Shaojin Wen bb8f2c0129
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 1/2 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 2/2 (push) Waiting to run
E2E Tests / channel-plugin E2E (nightly) (push) Waiting to run
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (push) Waiting to run
SDK Java / ubuntu-latest / Java 11 (push) Waiting to run
SDK Java / ubuntu-latest / Java 17 (push) Waiting to run
SDK Java / macos-latest / Java 21 (push) Waiting to run
SDK Java / ubuntu-latest / Java 21 (push) Waiting to run
SDK Java / windows-latest / Java 21 (push) Waiting to run
SDK Java / Real daemon E2E / Java 11 (push) Waiting to run
fix(cli): scrub inherited loader env vars from daemon session subprocesses (#8663)
* fix(cli): scrub inherited loader env vars from daemon session subprocesses

Daemon-mode sessions bound to one workspace inherited loader-affecting
env vars (NODE_OPTIONS with dev-harness --import hooks, NODE_PATH,
preload-class vars) from whatever shell launched the daemon, so
subprocesses in another workspace resolved modules through the
launching checkout's tree (fixes #8653).

Scrub the loader subset of RELOAD_EXCLUDED_KEYS from process.env at the
two process boundaries that host sessions: the daemon after freezing its
boot env (the frozen copy keeps loader vars so dev-mode ACP children can
still boot), and the ACP child after the relaunch/sandbox handoff (the
respawned child re-scrubs itself).

Fixes #8653

* fix(cli): reject loader env keys in initial .env load and log scrubs

A trusted workspace's .env could re-populate the loader-key slots that
scrubInheritedLoaderEnv() emptied in the daemon process, because
canApplyParsedEnvKey applied RELOAD_EXCLUDED_KEYS only on reloads.
Reject the loader subset on every .env application path so one
workspace's loader hook cannot reach other workspaces' session
subprocesses through the shared daemon env.

Also make the scrub return the removed keys and emit a stderr
breadcrumb naming them at both boundaries, so a session subprocess
missing an inherited var can be traced back to the scrub.

* fix(cli): reject loader env keys in serve fast path before env freeze

* fix(cli): deny npm_config_node_options and report rejected loader keys

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): match loader env keys case-insensitively and report settings.env rejections

* fix(cli): canonicalize loader env key spellings and scrub channel daemon workers

npm maps non-leading underscores in npm_config_* keys onto hyphens, so
npm_config_node-options injected NODE_OPTIONS exactly like
npm_config_node_options while slipping past every loader gate and scrub.
Canonicalize case and underscore/hyphen spelling on both sides of the
loader-key membership test, covering .env loads, settings.env
application, the serve fast path, and the inherited scrubs.

Channel daemon workers are spawned with the daemon's pre-scrub base env
but are not ACP children, so they never ran the self-scrub; mirror the
ACP-child scrub at the worker entry so nothing a worker spawns inherits
loader vars into another workspace.

Scope the settings.env rejection warning per workspace so a
multi-workspace daemon reports every workspace's rejection instead of
deduping them all under one label, revert the unread
loadServeFastPathEnvironment return value to void, and pin the
buildRuntimeEnvironment settings.env gate and the consume-once stash
reset with discriminating tests.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address review findings for loader env denylist

- report rejected loader keys through the daemon log after boot (per-workspace .env loads were silent once boot stderr was gone)

- accumulate serve fast-path rejected keys across loads instead of overwriting, dedupe, and use normalized env file paths for rejection sources

- restore scrubbed inherited loader env vars on embedded runQwenServe close()

- add regression tests for ENV scope coverage, reporter dedupe, fast-path accumulation, and post-boot daemon-log diagnostics

- scope docs: top-level env rejection does not apply to mcpServers[].env / hooks[].env; document serve loader-scrub behavior

* fix(tests): add writeStderrLineSafe to stdioHelpers mocks and sync env guard allowlist

* fix(cli): scrub loader vars from the daemon base env and retighten the denylist

The frozen daemonRuntimeBaseEnv was captured before the launch-env scrub,
so daemon-spawned session processes still booted under the inherited
loader — the child-side post-boot scrub ran after Node had already
consumed NODE_OPTIONS. The base env is now scrubbed before the freeze
(except under the DEV=true harness, whose .ts entries need the tsx
loader), and close() restores the host's launch env from a pristine
snapshot.

Denylist scope now follows the injection-vs-search-path split: adds the
npm config-file redirect keys, ZDOTDIR, and a BASH_FUNC_* prefix rule;
moves ENV/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH back to their reload-only
tier (mainstream toolchain compatibility); blocks QWEN_CLI_ENTRY and
NODE_EXTRA_CA_CERTS from project .env files. The ACP-child scrub is
gated on the daemon stamp (QWEN_CODE_SERVE) so direct editor ACP
integrations keep the user's exported environment, and the daemon's
per-workspace .env rejections are now reported from
buildRuntimeEnvironment.

* fix(cli): block DEV spoofing, case-insensitive env exclusions, serve boot env restore (#8663)

Address round-6 review: DEV joins the hardcoded project-env exclusions so a
workspace file cannot disable the daemon's loader-env scrub; the hardcoded
tier is enforced case-insensitively (Windows env lookup is case-insensitive)
via isHardcodedProjectEnvExclusion at every application gate; runQwenServe's
catch restores the scrubbed launch env and detaches the rejection reporter
when startup fails after the scrub. Tests gain the matching regressions,
home-env hermeticity, source-scoped warning filters, and tmpdir cleanup; the
unreachable reload delete-pass loader guard and its vacuous test are removed.

* fix(cli): match the reload-excluded env tier case-insensitively too

Round-6 follow-up: R6-3 named RELOAD_EXCLUDED_KEYS.has() among the gates a
case variant slips, but the hardcoded-tier fix left the reload-only keys
(QWEN_SERVER_TOKEN, PATH, HOME, TMPDIR, …) on exact-case matching. On
Windows a lowercase twin names the same OS variable, so a mid-session
settings.env/.env edit could still rotate the daemon token or move PATH
through a case respelling. Fold the reload tier the same way and pin it
with a reload-behavior regression test. Also note DEV in the settings.md
exclusion docs.

* test(cli): redirect HOME in environment.test.ts for full home-env hermeticity

The source-scoped warning filters fixed the warning-count assertions, but
the process.env assertions (e.g. 'never applies entrypoint or trust-anchor
keys') still read state a real home .env can pollute: home scope
deliberately bypasses the hardcoded exclusions, so a dev machine with
QWEN_CLI_ENTRY in ~/.env applies it and fails the test while CI stays
green. Redirect HOME/USERPROFILE to an empty temp dir in beforeEach —
verified by running the suite with HOME pointed at a poisoned home.

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
2026-08-08 16:11:39 +00:00
..
assets feat: support workspace display names (#7179) 2026-07-20 15:16:44 +00:00
design fix(cli): scrub inherited loader env vars from daemon session subprocesses (#8663) 2026-08-08 16:11:39 +00:00
developers feat(serve): Expose active work state (#8588) 2026-08-08 06:34:20 +00:00
e2e-tests feat(worktree): Phase D — startup --worktree flag + symlinkDirectories + PR refs (#4381) 2026-05-27 17:04:51 +08:00
images fix(web-shell): render built-in tag icons (#7024) 2026-07-17 15:33:34 +00:00
plans feat(channels): add Feishu ask-user question cards (#8578) 2026-08-08 04:20:17 +00:00
superpowers feat(cli): reference prior sessions via @ and add completion tabs (#7302) 2026-07-24 06:11:48 +00:00
users fix(cli): scrub inherited loader env vars from daemon session subprocesses (#8663) 2026-08-08 16:11:39 +00:00
verification/abort-controller-refactor fix(core): stop AbortSignal listener leak in long sessions (MaxListenersExceededWarning) (#4366) 2026-05-26 14:21:49 +08:00
_meta.ts feat: refactor docs 2025-12-05 10:51:57 +08:00
index.md fix: lint issues 2025-12-19 15:52:11 +08:00