Repository navigation
Replies: 3 comments 1 reply
|
你的报告质量很高(对照实验、排除项、ACL 观测与代码逐条对得上)。你引的两段"包内自带说明"我逐字找到了源码位置 —— 而且这恰好能让两条你标为"部分吻合但不足以解释"的线索直接结案。另外你有两处排除逻辑不成立。 1. 你引的两段,源码逐字在此
2. ⭐ 因此「keep-alive 组缺失」可以排除
⇒ 你 §5 第 12 项写"现有证据不足以支持该路径" —— 方向要改:这不是"证据不足",而是排除该路径的正面证据。建议把它从怀疑清单里划掉。 3. ⭐ 你漏掉的第四个差异(也是我建议上游先查的一处)你说 workspace-write 相对 read-only 多做了三件事(ACL / 标签 / TMP 重写)——还有第四件:
setTokenDefaultDaclGrant(api, restrictedToken, this.tempWriteSidPtr ?? this.writeSidPtr ?? worldSid)两种模式给「令牌默认 DACL」加的 SID 不同(read-only 走
4.
|
|
补充证据与一处更正:崩溃与子进程无关,故障域在 workspace-write 的沙箱供给环节 先更正本线程里的一处假设:该故障并非 pwsh 7 或 .NET 特有。同一台机器、桌面版内置 0.2.0-rc.2、随包自带的 runner,除模式与子进程之外参数完全相同,结果如下。
四点结论:
复现方式(参数说明;路径含空格时请调用方自行加引号):
与 9510 的区别(依据本线程上一条回复的描述):本工作区上已存在 S-1-4 开头的授权项,说明 grantWrite 曾经成功过,它同时写 DACL 与标签,因此本文故障点在更后面的子进程创建与初始化阶段,与预授权缺 WRITE_OWNER 的 Win32 5 失败不是同一故障。 建议排查方向(尚未证实):workspace-write 相对 read-only 的独有差异目前收敛到三处。README 说明 keep-alive 组缺失会让早期 DLL 初始化以 0xC0000142 死亡,而令牌默认 DACL 属于同一类开关,因此建议优先看 setTokenDefaultDaclGrant 的实参在 workspace-write 下由 Everyone 变为能力 SID 这一处;其次是工作区与私有临时目录的授权与 Low 标签;再次是 TMP 与 TEMP 重写。另外建议把子进程退出码与 stderr 如实回传:目前 0xC0000142 被静默镜像为零输出,使用者拿不到任何可读原因。 环境:桌面版内置 @deepseek-ai/dsh-* 0.2.0-rc.2;pwsh 7.6.6;node 24.18.1;Windows。 |
|
你这张表把变量消掉了一个:五个子进程(含 1. 候选差异收到两处(Low 标签可以划掉)你列的"三处独有差异"里,低完整性标签不成立:
restrictTokenIntegrity(api, restrictedToken, lowLabelSid)它在两种模式下都执行(紧接着 于是只剩两处:
2. ⭐ 一条新假设:
|
| 模式 | 默认 DACL 新增 ACE 的 SID | 该 SID 是否在令牌常规组里 |
|---|---|---|
| read-only | Everyone |
是 |
| workspace-write | 私有 temp SID / 工作区 SID(S-1-4-x-y) |
否(只进限制列表) |
假设:如果一个新建对象的 DACL 只命名一个"只存在于限制列表"的 SID,那么 pass-1(常规检查)无从匹配 ⇒ 对象对创建者自己也变成不可访问 ⇒ 而进程初始化期间映射 DLL 恰恰就是在创建对象 ⇒ 0xC0000142、零输出。这与你观察到的"连 cmd.exe 都死在 DLL 初始化"完全对得上。
3. ⭐ 一行判定实验(诊断用,不是修复)
把 index.ts:304 的 SID 强制成 worldSid:
setTokenDefaultDaclGrant(api, restrictedToken, worldSid) // 诊断:让 workspace-write 也命名 Everyone然后重跑你那张表的 cmd.exe 一行:
- 若
cmd.exe起来了 ⇒ 差异确实在这一条 ACE 的 SID 上,假设成立; - 若仍然 0xC0000142 ⇒ 差异在第二处(私有 temp 目录及其 ACL/标签),请把
--temp换成 ambient 目录再试一次,两者可完全分离。
:301-303 明确写了选 temp SID 是有意的 —— 目的是"防止某个会话 temp 树里的默认-DACL 对象拿到共享的工作区能力"。真按 worldSid 修,受限子进程新建的所有对象都会带上 Everyone:(F),而它们不在任何被贴 Low 标签的目录里 ⇒ 同用户的任意 Medium 完整性进程都能写它们。所以请把这条写成"用于定位的实验",并把它作为对上游的问题提("index.ts:292-303 的取舍理由是否需要补充 pass-1 的论证")。
4. 你那条 msys2 记录是对文档的独立确认(建议保留)
read-only 下 Git Bash 报"signal pipe 创建被拒(Win32 5)",与 packages/sandbox/sandbox-windows-acl/README.md:102 一带记录的命名管道边界一致 ⇒ 这是一个额外收获,说明你的探针可靠。建议在报告里点明"这解释了为什么换 Git Bash 不是出路"。
5. 你与 #9510 的区分正确
你写"本工作区已存在 S-1-4 授权项 ⇒ grantWrite 曾经成功 ⇒ 本文故障在更后面的子进程创建与初始化,与缺 WRITE_OWNER 的 Win32 5 不是同一故障" —— 完全正确,而且这个区分很重要(grantWrite 一次同时写 DACL 与 LABEL,所以有那个 ACE 就证明它成功过)。建议在报告开头就把这句放上去,避免维护者把两帖混为一谈。
6. 退出码与 stderr 回传:你说得对,缺口在这两行
packages/sandbox/sandbox-windows-acl/assets/diagnose-windows-sandbox-acl/…与src/runner.ts:210-227:runner 在子进程正常退出时如实镜像其退出码(:221 process.exitCode = exitCode)⇒0xC0000142被如实报成命令失败、零输出。windows-acl-run:这个诊断签名只在 runner 自身失败时才打印(:40-43);sandbox-local/src/index.ts:241的fatalSignatures: ['windows-acl-run: ']也据此判定 ⇒ 本故障必然不会带该签名。
⇒ 所以你 §8.3 的诉求(把子进程退出码与 stderr 如实回传、并给出可读原因)有明确依据,建议照原样保留。
7. 边界(按规矩标注)
- 我无法在本机证伪或证实第 2 节那条假设 —— 那需要 Windows 受限令牌实验,仓库里没有。
- 你建议的"其次是工作区与私有临时目录的授权与 Low 标签;再次是 TMP 与 TEMP 重写"这个排序,我同意第 2 项应提到与第 1 项并列(因为 Low 标签与模式无关,所以第 2 项里真正剩下的是私有 temp 目录的存在与否,而不是标签)。
- 环境与版本我按你给的对齐(桌面内置
0.2.0-rc.2);相关代码在origin/master(=dsh-v0.2.1-alpha.2)上一致。
Uh oh!
There was an error while loading. Please reload this page.
@deepseek-ai/dsh-*@0.2.0-rc.2;更新通道nightlyC:\Program Files\PowerShell\7\pwsh.exe)workspace-write(受限)全部失败;read-only(受限)正常1. 摘要
在 Windows 上,当会话的文件策略为
workspace-write时,任何一条 shell 命令都会在进程初始化阶段立即失败:danger-full-access下正常;read-only时,受限 shell 反而能正常工作(exit 0,正常输出)。因此问题不是“受限令牌机制不可用”,而是专属于
workspace-write的沙箱供给路径(ACL 授权、完整性标签、TMP 与 TEMP 重写)执行之后,受限子进程无法完成早期 DLL 初始化。该现象在以下条件下均稳定复现:工作区与安装目录位于非系统盘(D:)、位于系统盘(C:)、工作区为全新空目录、临时目录与工作区重叠或分离、临时目录长名或 8.3 短名、父进程有控制台、第三方 HIPS 安全软件全防护开启、存在旧版本残留。以上变量已逐项排除(见第 5 节)。
2. 环境(已打码)
XXX\XXXD:\Program Files\DS(非系统盘)C:\Users\XXX\.dsh(DSH_HOME,系统盘)C:\Users\XXX\.dsh\profiles\desktop(DSH_PROFILE=desktop)D:\XXX\XXX(非系统盘,NTFS;普通目录,非 junction,非 subst,非网络盘)permissions.sandbox = workspace-write,approval = askHipsDaemon与内核驱动sysdiag.sys、hrdevmon.sys、hrwfpdrv.sys均为 Running@deepseek-ai/dsh-root@0.1.3-alpha.1),安装 0.2.0 桌面版时未卸载3. 现象与期望
3.1 现象
sandbox=workspace-write下,任何 shell 调用(含Write-Output "ok"这类零副作用命令):3221225794或0xC0000142(STATUS_DLL_INIT_FAILED);danger-full-access后,同一命令立即正常(输出hello)。read-only后,受限 shell 正常(输出SANDBOX-OK,exit 0)。3.2 期望
workspace-write下 shell 可用,且写入被限制在工作区与私有临时目录内;0xC0000142暴露给用户;4. 关键定位证据
4.1 实际进程链(在放宽模式下抓取)
结论要点:
app.asar内的 subprocess runner(@deepseek-ai/dsh-subprocess-local@0.2.0-rc.2)与@deepseek-ai/dsh-sandbox-windows-acl@0.2.0-rc.2、@deepseek-ai/dsh-pwsh-sandbox@0.2.0-rc.2;与旧版残留、与安装盘符无关。windows-acl-run: <detail>并以 127 退出),说明 runner 已成功启动,是它下面的受限子进程在 DLL 初始化阶段死亡。pwsh相关崩溃记录,说明 pwsh 很可能从未执行到用户代码。4.2 最小复现(不经过 harness,直接调用打包的 runner)
说明:桌面程序是 GUI 子系统进程,从终端调用时不会阻塞,也拿不到输出,需用
Start-Process -Wait一类方式等待并重定向 stdout 与 stderr(完整脚本见附录 A)。4.3 对照结果(同一父进程、同一 runner、同一时间窗)
workspace-writeworkspace-writeXXX~1)workspace-writeread-onlySANDBOX-OK4.4 参考:包内自带的实现说明(随产品分发的文档与代码注释)
WRITE_RESTRICTED受限令牌,限制 SID 列表:read-only:[登录 SID, EVERYONE]workspace-write:[登录 SID, EVERYONE, 工作区 SID, 可选临时 SID](登录 SID + EVERYONE)是保活组:“缺少它时早期 DLL 初始化会以0xC0000142死亡”;CREATE_NO_WINDOW与CREATE_NEW_CONSOLE创建的子进程会在 DLL 初始化期间以STATUS_DLL_INIT_FAILED(0xC0000142)死亡;子进程共享宿主控制台,基于管道的 stdio 重定向不受影响。”这两条与本次现象部分吻合但不足以解释:按代码
workspace-write仍保留保活组;且父进程有控制台时依然失败(见第 5 节第 7 项)。5. 已尝试的排查、假设与结果
danger-full-access后执行workspace-write)Everyone: 拒绝 DeleteSubdirectoriesAndFiles、DSH 自身的S-1-4-XXX-XXX: 允许 Write、Delete、DeleteSubdirectoriesAndFilesALL APPLICATION PACKAGES与ALL RESTRICTED APPLICATION PACKAGES);再用 C 盘全新工作区跑workspace-writeread-only成功,workspace-write仍失败read-only作对照read-only受限 shell 成功read-only亦应失败)dsh命令、运行中的旧进程、端口占用、profile 依赖dsh-context与zodDSH Doctor Supervisor(Ready),其目标脚本已不存在(登录 SID, EVERYONE)workspace-write的供给副作用之后6. 影响面
workspace-write下workspace-write下read-only下7. 用户侧无法解决的部分
workspace-write的前提下获得受沙箱约束的 shell。 沙箱供给与受限子进程创建都在产品内部完成,用户侧没有任何可用开关可以改动这一层。app.asar内的打包产物,而失败发生在进程初始化阶段,连用户代码都未执行。read-only受限 shell 正常。workspace-write,把每一条 shell 命令单独放宽(需要逐条批准);8. 对开发者的问题定位建议
workspace-write供给完成后补一步自检:用受限令牌起一个最小进程(例如cmd /c exit 0或pwsh -Command exit),捕获退出码;失败即 fail-closed,并给出可读原因,而不是让用户看到裸0xC0000142。workspace-write是否给子进程附加了低完整性标签,以及该标签与早期 DLL 初始化(如 CNG 设备写入)之间的相互作用。windows-acl-run: <detail>一类诊断信息,失败信息量几乎为零。read-only通过而workspace-write失败这组对照纳入 Windows 冒烟用例,且必须覆盖父进程无控制台的桌面宿主场景。9. 打码对照
XXX\XXXD:\XXX\XXXC:\Users\XXX\...S-1-4-XXX-XXXS-1-15-3-XXXXXX~1session-XXX未打码且需保留的信息:产品与包版本号、Windows 版本号、盘符与是否系统盘、NTFS、标准系统路径(
C:\Program Files\...)、公开的第三方软件产品名、退出码与命令原文。附录 A:可直接运行的复现脚本(PowerShell)
预期输出(本机实测):
附录 B:本次排查使用的只读检查(可复现)
sandboxMode与permissions(值:workspace-write,approval=ask)。subprocess-local与sandbox-windows-acl的 runner 与最终pwsh的 argv。pwsh、DeepSeek、Harness)与 WER 报告目录,结果 0 条。app.asar头部目录,列出@deepseek-ai/dsh-*包名与版本(0.2.0-rc.2)。--mode read-only与--mode workspace-write交叉对照,分别更换工作区盘符、临时目录位置与命名形式。以上均为只读操作;除自建的临时测试目录外,未修改任何文件、权限与配置。
All reactions