Repository navigation
Replies: 3 comments 1 reply
|
Confirmed at the source of the scrubber, and the specific reason your variable survives is worth quoting because it is not an oversight — it is the scrubber's stated scope.
export const SENSITIVE_ENV_PATTERN = /KEY|PASSWORD|SECRET|TOKEN/i // :47
export function scrubbedParentEnv(): Record<string, string> { // :66
const env = {}
for (const [key, value] of Object.entries(process.env)) {
if (value !== undefined && !SENSITIVE_ENV_PATTERN.test(key) && !key.toUpperCase().startsWith(DSH_ENV_PREFIX)) env[key] = value
}
...
}
The doc comment at Two fix shapes, and they are not equivalent:
I would argue for (2) as the direction and (1) as the immediate patch, because (2) is the only one that keeps working when the next Electron variable appears — and it also stops you from having to re-audit this every time someone adds a knob. One thing worth adding to the report: the same leak plausibly affects any other detached-launch path that reuses |
|
Implemented shape (1) from your comment above, but scoped to the launch path rather than to the scrubber, so harness children keep the switch: // packages/host/open-in-app/src/resolver.ts
const guiLaunchEnvironment = (
overrides?: Readonly<Record<string, string>> | undefined,
): NodeJS.ProcessEnv => {
const env: NodeJS.ProcessEnv = { ...scrubbedParentEnv() }
delete env.ELECTRON_RUN_AS_NODE
delete env.ELECTRON_NO_ATTACH_CONSOLE
return { ...env, ...overrides }
}
// …
env: guiLaunchEnvironment(options.env),Two details that cost time while writing it, worth recording before someone re-implements this:
Branch with the change, one commit, two files, ready to cherry-pick: master...Yang-SVVG:fix/open-in-app-electron-run-as-node
Verified on a real install (DSH desktop 0.2.1-rc.2, Windows 11, VS Code 1.141.0 at a non-default path Same root cause as #10294, #9920, #9689, #9254 and #8970 — eight threads for one defect, which is itself a signal about discoverability. Two follow-ups I deliberately left out of this patch: |
|
Your ordering point is the part that would have bitten anyone re-implementing this. Where the variable comes from, for the record: it is not only a user shell setting. The desktop shell spawns the host with One change I would make to the patch: put the deletion inside
Two tests I would want in the diff, because they pin the ordering trap you hit: a parent with
|
Uh oh!
There was an error while loading. Please reload this page.
Where to post: deepseek-ai/deepseek-harness has Issues disabled; bug reports go to Discussions → General, titled with a [Bug] prefix. Paste this file as the body. If maintainers prefer support threads, the same body fits Q&A unchanged.
Environment
DSH desktop 0.2.0-rc.2, Windows 11 (10.0.26200), x64
VS Code 1.142.0, installed at D:\Microsoft VS Code (non-default path; resolved correctly through HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Code.exe)
Profile: desktop (bundles: @deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app, dsh-ops, dshmarket)
Summary
The Session-header "Open In…" menu lists VS Code, but choosing it never takes effect: the split button keeps showing File Explorer (default) and no choice is persisted. The same failure applies to the document-preview "Open" action. Launching the identical executable from a terminal works.
Cause: the desktop app runs its backend through the Electron binary acting as Node (process.execPath + ELECTRON_RUN_AS_NODE=1), so the backend's process.env carries that variable. open-in-app launches applications detached with scrubbedParentEnv(), which strips only /KEY|PASSWORD|SECRET|TOKEN/ names and DSH_* — the Electron selector survives, and any launched Electron application (VS Code, Cursor, Windsurf, …) then starts as plain Node, receives the workspace directory as if it were a script argument, and exits non-zero immediately.
Because launchWatchMs (default 1000 ms) classifies a non-zero exit inside the window as a failed launch, the route reports failure and the client never stores the choice, so the UI looks like the entry "cannot be selected".
Steps to reproduce
Install VS Code (anywhere; App Paths or the file locators resolve it).
Open a Session, click the chevron of the header "Open In…" split button.
Choose VS Code. Nothing opens; the default stays File Explorer.
Compare with the terminal, which succeeds:
代码块
VS Code opens the directory normally.
Evidence
The host process and everything it spawns see the selector:
代码块
代码块
node -e "const{spawn}=require('node:child_process');const p=spawn('D:\Microsoft VS Code\Code.exe',['C:\Users\hjc\Documents\deepseek-harness\default-workspace']);p.on('exit',(c,s)=>{console.log('exit',c,s);process.exit(0)})"
exit 1 null (after 55 ms)
The executable itself is fine — it is signed Microsoft VS Code 1.142.0 (FileDescription: Visual Studio Code, FileVersion: 1.142.0, valid Authenticode signature). Under the inherited environment it answers as Node:
代码块
代码块
Root cause
@deepseek-ai/dsh-subprocess — the scrubbed child environment:
js
const SENSITIVE_ENV_PATTERN = /KEY|PASSWORD|SECRET|TOKEN/i;
function scrubbedParentEnv() {
const env = {};
for (const [key, value] of Object.entries(process.env)) {
if (value !== void 0 && !SENSITIVE_ENV_PATTERN.test(key) && !key.toUpperCase().startsWith("DSH_")) env[key] = value;
}
for (const [name, value] of Object.entries(proxyEnvironmentForChild())) { /* … */ }
return env;
}
@deepseek-ai/dsh-host-open-in-app — the launcher:
js
const child = spawn(command, [...args], {
detached: true,
stdio: "ignore",
windowsHide: options.windowsHide,
env: { ...scrubbedParentEnv(), ...options.env },
});
ELECTRON_RUN_AS_NODE matches neither exclusion, so it reaches every spawned application.
The desktop build is what puts it in the backend's environment (support launcher):
js
packageManager: {
command: process.execPath,
args: ["--expose-internals", /* … /],
env: {
ELECTRON_RUN_AS_NODE: "1", // backend runs the Electron binary as Node
DSH_DESKTOP_NODE_EXECUTABLE: process.execPath,
PATH: / … */,
},
},
Suggested fix
Exclude runtime selector variables from the inherited environment in scrubbedParentEnv() (@deepseek-ai/dsh-subprocess), keeping the explicit adapter entries authoritative:
js
// Names that only make sense for this host's own Electron-as-Node runtime. A launched
// application must never inherit them: VS Code and other Electron apps would start as Node
// and exit immediately, which open-in-app reports as a failed launch.
const HOST_RUNTIME_ENV = new Set(["ELECTRON_RUN_AS_NODE", "ELECTRON_NO_ATTACH_CONSOLE"]);
function scrubbedParentEnv() {
const env = {};
for (const [key, value] of Object.entries(process.env)) {
if (value === void 0) continue;
if (SENSITIVE_ENV_PATTERN.test(key)) continue;
if (key.toUpperCase().startsWith("DSH_")) continue;
if (HOST_RUNTIME_ENV.has(key.toUpperCase())) continue;
env[key] = value;
}
/* … */
}
This keeps the GitHub Desktop entry working: that catalog entry deliberately sets env: { ELECTRON_RUN_AS_NODE: "1" } to run its packaged cli.js, and the spread order in launchDetachedApp (...scrubbedParentEnv(), ...options.env) still lets the explicit entry win.
A narrower alternative is to delete the name inside launchDetachedApp before spreading options.env; filtering the inherited environment is preferable because the same leak affects any detached child that happens to be an Electron binary.
Impact
All Electron-based catalog entries (VS Code, VS Code Insiders, Cursor, Windsurf, Zed, and any other application honoring the selector) cannot be launched from the header or the document preview.
File-manager entries are unaffected because they use shell-open, which explains why File Explorer works and the same action on VS Code does not.
Symptom is silent: the failed launch shows at most a transient toast, and the remembered choice is not updated, so it reads as "this menu item cannot be selected".
中文摘要
Windows 上「Open In…」里选 VS Code 不生效:桌面端用「Electron 二进制 + ELECTRON_RUN_AS_NODE=1」 拉起后端,后端 process.env 因此带上这个变量;open-in-app 启动外部应用时用的 scrubbedParentEnv() 只剔除 KEY/PASSWORD/SECRET/TOKEN 与 DSH_*,变量被继承,VS Code 于是以 Node 模式启动、约 55 ms 后退出码 1。launchWatchMs(默认 1000 ms)把它判为启动失败,选择因此不会 被记住,界面看起来就是「无法选中」。建议在 scrubbedParentEnv() 里排除该运行时选择变量,显式 adapter 条目(如 GitHub Desktop 的 ELECTRON_RUN_AS_NODE: "1")仍应生效。
All reactions