[Bug][Windows] Windows ACL 沙箱(workspace-write)三个授权缺陷:受保护 DACL 子目录永不获授权 / desktop 根授权缓存不复核不自愈 / 标准用户+非系统盘 grantWrite 失败(Win32 5) #8409
Replies: 5 comments
缺陷 A:受保护 DACL 子目录永远无法写入症状会话开始时(若同时命中缺陷 C)每一条 shell 命令在执行前就失败: 排除缺陷 C 后(工作区根授权成功、根可写),工作区内不通过 NTFS 继承获得权限的子目录仍全部拒绝写入,且缺失是永久性的(授权侧跳过逻辑只看根,见机理节)。 复现# 0) 前提:workspace-write 会话已能正常受限写入(根授权完成)
# 1) 非受限侧准备夹具(DACL 受保护,不含能力 ACE):
mkdir <工作区根>\sub-protected
icacls <工作区根>\sub-protected /inheritance:r /grant "$env:USERNAME:(OI)(CI)F"
# 2) 受限侧(沙箱内 shell):
'x' | Set-Content <工作区根>\sub-protected\f.txt
# → 拒绝访问(Get-Content 读取却正常)实测矩阵
触发条件触发:工作区内任何 DACL 不继承根的子目录。现实来源: 不触发(实测):受限进程自建目录、宿主进程(write 工具)创建的目录、任意深度嵌套、同卷移入的目录(Windows 自动补继承)。 profile 归属:无关。desktop 与 agentless runner(直接调 |
缺陷 B:desktop 根授权缓存陈旧,ACE 丢失后连根都写不进且不自愈症状desktop seam 首次成功授权后缓存「已物化」;此后根上的能力 ACE 被移除/丢失(现实中如用户重置 ACL、从备份恢复目录、某些「权限修复」工具),受限写入连工作区根一起失败,不会自愈(后续调用不再重新授权),直到桌面端/工作区服务器重启。 复现# 1) 会话内先成功执行一次受限写(seam 物化并缓存根授权)
# 2) 非受限侧摘除根上的能力 ACE(icacls 处理不了未映射 SID,须 .NET):
$acl = Get-Acl <工作区根>
$cap = @($acl.Access | ? { "$($_.IdentityReference)" -like 'S-1-4-*' -and -not $_.IsInherited })
$cap | % { $acl.RemoveAccessRuleSpecific($_) }
Set-Acl <工作区根> $acl
# 3) 受限侧再写工作区根 → 拒绝访问;此后每次调用都失败,重启桌面端才恢复agentless 对照同破坏下,agentless runner 第二轮调用写入成功且能力 ACE 自动补回(DACL 快照可见原能力 SID 重现)——runner 每次 spawn 自行 agentless runner 直调方式(对比实验用): |
缺陷 C:标准用户 + 非系统盘工作区,grantWrite 报 Win32 5,会话内全部命令启动前失败症状沙箱对工作区根做 ACL 授权这一步被 Windows 拒绝(错误 5 = 拒绝访问),命令本体根本没有运行。错误只抛裸 Win32 串,没有任何引导。 复现触发条件标准用户 + 工作区位于默认 ACL 不给当前用户 DSH 内置的 ACL 诊断技能( 观测到的机理(源码证据,行号为
|
|
Thanks — this is the most complete report of the Windows ACL backend so far, and defect B in particular is a cell nobody had named. Three things to add, all of them read off Defect B has a layer above the one you foundYour attribution is right about the symptom — the root persists and never self-heals until the desktop restarts — and it is one layer higher than the ACL module. The provisioning check that "reads the DACL" is not what is being skipped here; it is not reached at all:
So "the cache is stale" is true but understates it — the cache is the only thing consulted, and it is keyed per provider lifetime rather than per ACL state. Defect A's trigger is a DACL that does not inheritYour fixture is the one worth keeping: What has shipped as a plugin
- insert:
- id: sandbox-grant-advisor
name: '@argszero/cordis-plugin-sandbox-grant-advisor'Since 0.14.0 (published today) its fourth family forks on breadth into exactly your three shapes, and defect B is the third branch: a refused root is neither of the propagation halves, no command reaches it, and the recovery is the user's — restart the provider, which empties the map. Defect A is the DACL branch (with your Defect C is the one the built-in |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
0.2.0-rc.2,nightly 更新通道workspace-write,approval =ask@deepseek-ai/dsh-sandbox-windows-acl:WRITE_RESTRICTED受限令牌 + 确定性工作区能力 SID(S-1-4-*)+ Low 完整性标签 + world 拒绝FILE_DELETE_CHILD,一次SetNamedSecurityInfoW写入runner.js)均复现,各缺陷归属见下文摘要
实测发现 Windows ACL 沙箱存在 3 个授权缺陷(A / B / C)。用户侧最直观的症状是「沙箱写权限不对工作区子目录开放」,实测其成因与另两个缺陷相关但独立:
Authenticated Users=Modify,用户无显式 ACE)时,授权所需的 Low 标签编辑要求WRITE_OWNER而当前用户没有 →SetNamedSecurityInfoW返回 Win32 5 → 会话内所有受限命令在启动前即失败。内置 ACL 诊断技能可修复,但工具错误只抛裸 Win32 串,没有任何引导。附带发现
icacls /remove无法处理未映射的能力 SID(静默处理 0 个文件),与源码 README 记载的ERROR_NONE_MAPPED (1332)一致;手工清理须用 .NET 按 SID 操作。read工具读 asar 内路径时报Cannot mix BigInt and other types(工具层缺陷,与沙箱无关,一并反馈)。测试范围声明
仅覆盖 Windows ACL 沙箱的 desktop 与 agentless 两种形态;junction/reparse 子树、跨卷移入(copy 语义,预期重新继承)、FAT/exFAT 卷未测;缺陷 B 的缓存生命周期上界(新会话是否重建 server)未验证,但不影响上述结论。
All reactions