【BUG REPORT】workspace-write allows recursive deletion of the entire workspace with zero confirmation
#149
Replies: 3 comments
|
Confirmed the mechanism against the code, with two corrections that matter for whoever picks this up. The preset table and Correction — the blast radius differs by backend.
Same disaster either way, but "delete the workspace root" is not accurate under bwrap, and a fix that only guards the root would leave the bwrap case fully exploitable anyway. Constraint on suggested fix #1. It cannot be implemented in |
|
这个事故现在可以先加一道独立于主 Agent 的拒绝门。 dsh plugin --profile web add pi2dsh@0.10.0
dsh plugin --profile web add pi-approval-guardian
export PI_APPROVAL_GUARDIAN_MODEL=deepseek-official/deepseek-v4-flash
export PI_APPROVAL_GUARDIAN_POLICY='禁止删除 workspace 根目录或递归清空整个项目;任何 rm -rf、shutil.rmtree、Remove-Item -Recurse 涉及 workspace root 或其全部内容时必须拒绝。'仓库和复现说明: https://github.com/weijiafu14/pi2dsh 这不是替 DSH core 宣称问题已经修复:最稳妥的上游修复仍应当落在 shell/sandbox 执行层,做确定性的 workspace-root destructive-op guard。这个插件方案的价值是今天就能给现有安装加第二道、不同模型判定的防线,也能覆盖一部分不止 |
|
Confirming the mechanism and adding the one thing that makes the fix tractable: this is the third member of the same sandbox-inconsistency family, and each has a different correct layer. The family
Why the fix can't live in
|
Uh oh!
There was an error while loading. Please reload this page.
Summary
Under the
workspace-writepermission preset, an agent can recursively delete the entire workspace root (rm -rf <workspace>/shutil.rmtree(workspace_root)) with no approval prompt, no sandbox denial, and no confirmation of any kind. The project is destroyed silently; recovery depends entirely on external backups/remotes.Reproduction
workspace-writepreset (sandbox: workspace-write,approval: ask).rm -rf /path/to/workspace(or any Pythonshutil.rmtreetargeting the workspace root).Root cause
The permission model authorizes by path space, not by operation semantics:
dsh-sandbox-local) expressesworkspace-writeas a bwrap bind mount (--bind workspaceRoot workspaceRoot) / Landlock allow-list. To the kernel, recursively deleting a directory tree is just a sequence of in-rangeunlink()calls — indistinguishable from deleting a temp file.approval: 'ask'policy only fires on out-of-policy retries (escalation requests). Deleting the workspace root is fully in-policy, soasknever triggers.dsh-permission-presets) contains onlyworkspace-writeanddanger-full-access.Real-world impact
This caused an actual incident: a test-cleanup bug (
shutil.rmtree(os.path.dirname(db_path))in afinallyblock, wheredirnameresolved to the project root) silently deleted an entire project — code,.git, virtualenv, docs — with zero prompts. Recovery was only possible because the repository had been pushed to GitHub beforehand.Suggested fixes (any of these would have prevented it)
destructive-ops: askoption, or extend theaskpolicy to also match dangerous operation patterns rather than only out-of-policy retries.workspace-writeincludes deleting any content inside the workspace, so the permission name does not understate its blast radius.Environment
@deepseek-ai/dsh0.1.0-rc.6References
dsh-permission-presets— onlyworkspace-write/danger-full-access;approvalgates out-of-policy retries only.dsh-sandbox-localbwrapProfileArgs:workspace-write→--bind workspaceRoot workspaceRoot.All reactions