Repository navigation
[Windows] 工作区包含 TEMP 时,workspace-write 下命令执行器整体失效,且报错无可操作指引 #9175
Replies: 5 comments
|
Confirming this from the source, and adding the facts that decide what can be fixed where — including one that is invisible from the outside: that sentence has two producers, and a fix has to satisfy both. The check, and why it fires before any child exists
export function assertTempRootOutsideWorkspace(workspaceRoot, tempRoot) {
if (containsDirectory(workspaceRoot, tempRoot))
throw new Error(`Windows ACL temp root must be outside the workspace: workspace=${workspaceRoot}; temp=${tempRoot}`)
}The session path reaches it from
Why the invariant exists, in the module's own words: "every child created below it would inherit the standing workspace capability." The private temp directory is meant to be the revocable half of the pair; placing it under the workspace root would put it inside the standing one, where it would stop being revocable. So this is a capability-disjointness rule, not a complaint about your setup — and The lever is the environment, not a policy fieldThe temp root is Two producers of one sentenceThe same assertion also runs on the child side, in the runner ( That split explains the shape of what you saw. A session-scoped call is refused by the parent before spawn — a thrown error in the tool result, your case. An agentless
On the three expectations
All three are upstream-shaped. What is reachable from outside is the diagnosis half, and that is the direction I will take: attach the remediation — both operands plus the One adjacent observation, for completeness: the backend does ship a diagnosis skill for denials it cannot explain ( |
|
A stopgap for this is published, and here is what it does.
It is a standalone npm plugin with its own public repository 1. When a command is actually refused. It recognizes the producer's own 2. Before the first command fails — the part this thread asked for. On Mount: - insert:
- id: sandbox-grant-advisor
name: '@argszero/cordis-plugin-sandbox-grant-advisor'The advisory half is always on and blocks nothing. An optional, off-by-default Two limits, stated plainly. The recognition and the containment are Finally, since the plugin is a stopgap rather than a fix: the assertion here is |
|
Thanks — this explains more than my report did, and the two-producer split accounts for something I could not. Confirmations from the same machine the report came from:
On the limit you stated — "the suite runs on macOS … it proves the decision layer, not the Windows path itself" — I can close that gap if it is useful. This machine reproduces the condition deterministically:
So both seats are exercisable on a real Windows path rather than a stubbed one:
If that is useful, say which seat matters first and I will run it and report back with raw output. One retraction for the record: my original report listed the PowerShell 5.1 observation as a possible clue. It is orthogonal to this defect — it concerns which shell the executor picks up, not the ACL path — so please disregard that line. |
|
Verdict: both seats fire on the real Windows path, in the order you described. The gap you named — "the suite runs on macOS … it proves the decision layer, not the Windows path itself" — is closed for both halves. The environment (the condition, live)
Before / after, on the same callOne Before mounting — the producer's sentence alone, one line, no advice: After mounting a fresh Seat 1 — pre-flight, before anything failedIt opened with the standing condition rather than waiting for a refusal:
It also carries the falsifiability you built in, which is the right shape for a pre-flight claim:
Seat 2 — the refusal's own reportThen the command was actually refused, and the second advisory arrived with it:
So the separation you described holds on Windows too — "the producer's own line and the carrier it came from are facts only the failure half can have, so a second advisory follows a real refusal." Observed exactly that way: standing report first, refusal report after the refusal, and the standing one explicitly defers to it ("this warning is not a substitute for the refusal's own report"). What this verifies, specifically
What remains unverified on WindowsI would rather name these than let the verdict read wider than the evidence:
The negative case is cheap from here and it is the one that closes the loop on the lever itself. Say the word if you want it before you take the upstream fix further; otherwise I will report back with it either way. |
|
Negative case for the temp-root family: confirmed. Moving the temp root out of the workspace cleared the condition — and the plugin responded exactly as designed, by going silent on that family and switching to a different one. How it was clearedPer the advisory's own remedy 1, Workspace unchanged: What changed at the refusalSame call, no escalation,
So three things are now observed rather than inferred:
A sequential exposure on this workspace shape — worth knowing
For anyone whose workspace is a profile parent or a drive root, "move the temp root" is therefore one step of two, not the fix — and the second step is the one with a blast radius. Which branch actually applies here, and why it mattersMeasured on the failing directory (unelevated, read-only):
That forces the second branch twice over: the unelevated And it is where I want to flag the ordering rather than the content. The advisory's grant branch, if reached by elevation, would have the backend write an inheritable Low integrity label — and on Your advisory does contain the correct escape ("sidestep the ACL entirely: create the workspace under One question on the version boundaryOur install is Still unverified on WindowsUnchanged from my last note: the runner carrier (agentless |
Uh oh!
There was an error while loading. Please reload this page.
摘要
在 Windows 上,当会话工作区包含系统的
TEMP目录时(本例:工作区 =C:\Users,TEMP=C:\Users\yangz\AppData\Local\Temp),workspace-write模式下命令执行器无法启动任何进程 —— 连echo test都失败。文件类工具(读写/检索)不受影响。失败不是以「降级到别的临时目录」或「明确提示改什么」的方式呈现,而是以一句无法据以行动的内部断言结束。
环境
0.1.5-rc.1(@deepseek-ai/dsh,全局 npm 安装)v24.16.011.13.010.0.19045(Build 19045)5.1.19041.6456(Desktop 版,非 PowerShell 7)workspace-writeC:\UsersTEMP/TMPC:\Users\yangz\AppData\Local\Temp最小复现
C:\Users(即用户目录的父目录,使TEMP落在工作区内部)workspace-write策略下执行任意命令,例如:实际行为
命令未被执行,返回:
echo也失败 —— 说明该检查位于执行器启动路径上,与具体命令是否触碰文件系统无关read/write/edit/glob/grep)在同一会话中工作正常,故障范围限于命令执行器期望行为
任一即可,按偏好排序:
%SystemRoot%\Temp、或自建一个位于工作区外的 ACL 临时根),并照常执行命令TEMP的目录,或设置DSH_TEMP_ROOT指向<路径>」,而不是只陈述一个内部不变式echo这种零副作用的命令都阻断影响
工作区设为
C:\Users的场景并非罕见 —— 用户目录的父级常被当作「我的东西都在这」的默认选择(本项目文档里C:\Users\<name>\...这类绝对路径也很常见),而 Windows 上TEMP默认就在C:\Users\<name>\AppData\Local\Temp。两者一撞,命令能力整体归零,用户只能靠文件工具干活,且从报错里看不出该改什么。临时规避(用户侧)
把文件策略提升到
danger-full-access后,同一命令正常执行:可作对照,证明问题出在该 ACL 前置检查,而非命令本身。
相关
说明
$PSEdition = Desktop,??运算符不被支持),与工具名pwsh所暗示的 PowerShell 7 不一致。All reactions