Repository navigation
Replies: 1 comment
|
核实到的部分:dsh-http-proxy 的策略层显式折叠两种大小写 —— packages/util/http-proxy/src/policy.ts:40:httpProxy: ['http_proxy', 'HTTP_PROXY'];boot 层的环境白名单用大写(packages/boot/app-boot/src/index.ts:111)。这与「管道里同时存在两种大小写」的报告吻合。 子进程环境最终如何把两份都发布出去、以及 PowerShell Env: 崩溃的确切触发点,我没有逐行钉死 —— 如果你把报错原文(Get-ChildItem Env: 的完整输出)贴出来,可以精确到行。你的修复方向(子环境统一为单一大小写)与 boot 层白名单思路一致。(基于 0.1.5-rc.2 源码核对。) |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
[Windows] Case-duplicate proxy variables in the child environment break PowerShell's
Env:provider (Get-ChildItem Env:throws "An item with the same key has already been added.")Summary
On Windows,
@deepseek-ai/dsh-http-proxypublishes both casings of each proxy variable (http_proxyandHTTP_PROXY) into the environment object handed to spawned children, so the child's Windows environment block contains case-duplicate names and PowerShell's case-insensitiveEnv:provider throwsAn item with the same key has already been added.— makingGet-ChildItem Env:/Get-Item Env:PATH/ls Env:unusable inside the DSH shell tool.Environment
@deepseek-ai/dsh0.1.5-rc.1 (npm global install) — reproduced on this version.masteror on the latest releasedsh-v0.1.5-rc.2(verified 2026-09-12:packages/util/http-proxy/src/policy.tsis byte-identical on both refs and still declares both casings for every field).spawn, not in version-specific Node behaviour — so Node 24+ behaves the same.pwshinstalled on this host).Steps to reproduce
(Any export mechanism works. No proxy actually needs to be listening — the variable merely has to exist.
HTTPS_PROXY,NO_PROXYand the lowercase spellings trigger it identically.)2. Close and reopen the terminal so the new value is present in the process environment block.
3. Start DSH:
Get-ChildItem Env:Expected behaviour
Get-ChildItem Env:lists the environment variables of the spawned PowerShell process, as it does in any terminal outside DSH.Actual behaviour
Get-Item Env:PATHandls Env:fail the same way. In the very same session the following both work, which isolates the fault to theEnv:provider rather than to the environment block itself:Impact: the agent's own PowerShell tool cannot enumerate environment variables. Any model-authored script that touches
Get-ChildItem Env:fails, which triggers retries and stalls. This is a known Windows/PowerShell failure mode for duplicated case-variant names (upstream: PowerShell/PowerShell#6305).Root cause
packages/util/http-proxy/src/policy.tsdeclares both casings for every policy field:On 0.1.5-rc.1 (and earlier) this constant lived in the sibling module
packages/util/http-proxy/src/install.ts; it was moved topolicy.ts, unchanged, onmaster. So on the reporter's version the same constant and the sameapplyPolicyEnvare ininstall.ts.applyPolicyEnv(policy)ininstall.tswrites both spellings intoprocess.env. On Windows this layer is harmless on its own, because Node'sprocess.envfolds names case-insensitively — whichwriteProxyEnv()in the same file already documents:proxyEnvironmentForChild()returns a plain JS object, which is case-sensitive, and assigns one entry per spelling:overlay['http_proxy']andoverlay['HTTP_PROXY']are two distinct properties here.packages/util/subprocess/subprocess/src/index.ts—scrubbedParentEnv()(published as@deepseek-ai/dsh-subprocess/lib/index.js) builds the child base with a plain object and then merges that overlay onto it:Enumerating
process.envon Windows yields the user's spelling exactly once (e.g.HTTP_PROXY), while the overlay contributeshttp_proxyas a new key of a case-sensitive object. The object returned tospawntherefore carries bothHTTP_PROXYandhttp_proxy.Windows
CreateProcessaccepts case-variant duplicates inlpEnvironmentand does not deduplicate them, so the PowerShell child really does receive two entries whose names differ only in case.Windows PowerShell 5.1 implements
Env:over a case-insensitive dictionary and throwsArgumentException: An item with the same key has already been added.when the second variant is inserted.Why this cannot be turned off
runProfile()inapps/cli/src/profile-boot.tsinstalls the proxy unconditionally:That call happens before
composeProfile()loadscordis.patch.yml, so a profile patch cannot prevent it.dsh-http-proxyis a plain library (its README states no mounting and no configuration are required), not a plugin line, so the loader'sdisabledmechanism does not apply. There is also no proxy-relatedDSH_*switch anywhere in the project (onlyDSH_HOME,DSH_TELEMETRY_DISABLED,DSH_SNAPSHOTand the internalDSH_LAUNCH_ENVIRONMENT_KEY).In-repo precedent for the fix
The sibling package already solves exactly this problem:
packages/util/launch-environment/README.mdstates that "on Windows, names are folded to uppercase before storage so case variants cannot split precedence", andpackages/util/launch-environment/src/index.tsimplements it:dsh-http-proxy's child overlay is the one path that bypasses that protection.Suggested fix
Any one of these resolves it; the first matches the precedent already in the repo:
proxyEnvironmentForChild(). Writing both casings exists only to satisfy undici's "lowercase wins" read order; on Windows the environment is case-insensitive anyway, so the duplicate buys nothing. Select the spelling byprocess.platform(uppercase onwin32), or reuse thedsh-launch-environmentfolding rule instead of hand-rolling names.scrubbedParentEnv(). When building the child env onwin32, collapse keys case-insensitively so no upstream overlay can ever produce a duplicate. This is the more robust place, sincescrubbedParentEnvis the single shared base for every spawner.DSH_*switch that suppresses proxy-environment publication to children would help as a stopgap — but it must be evaluated aftercomposeProfile()so a profile patch can actually set it.A regression test worth having: on
win32, assert thatObject.keys(scrubbedParentEnv())contains no two entries equal undertoUpperCase().Workaround
Clear every casing before starting
dsh, e.g. via a wrapper script:Note that the uppercase and the lowercase spelling each trigger the bug independently, so all six names must be cleared. Alternatively, use a terminal dedicated to DSH in which no proxy variable is exported.
All reactions