Tools guard that moves agent-issued `rm` targets to the macOS Trash instead of deleting, with a shell-aware lexer covering compound and disguised commands; a switch in Settings → General turns it off.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:NattoCB/dsh-safe-delete
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
A DeepSeek Harness host-side plugin that makes agent-issued
rmcommands recoverable: targets are moved to the macOS Trash instead of deleted, across GUI sessions, automation runs, headless bridges, and subagents. One switch in Settings → General turns it off — disabled, commands run with native DSH behavior.
Capabilities
- Recoverable deletion — an
rmin command position is denied and rewritten to/usr/bin/trash -v; the model receives a report of exactly what was moved, so nothing silently disappears. - Every session, one guard — registers once on the DSH tools registry; GUI chats, scheduled automations, headless bridges, and subagents are all covered with zero per-session wiring.
- Shell-aware interception — quote-preserving lexer catches
sudo rm,/bin/rm,env/nice-prefixedrm,VAR=x rm, andxargs rminside compound commands (&&,||,;,|). - Fail-safe by design — constructs that could hide an
rm($(...), backticks, subshells, heredocs,eval, nestedsh -c) are denied with guidance instead of rewritten; a failed trash is reported, never retried as real deletion. - Runtime switch — toggle in the web GUI (Settings → General → Safe Delete) or via
POST /safe-delete/config; the state persists across restarts in$DSH_HOME/storages/safe-delete.json.
How it works
The plugin installs one guard on the DSH tools registry. Every bash tool call is scanned before execution:
flowchart LR
A["bash tool call"] --> B{"rm in command<br/>position?"}
B -- "no" --> C["native execution"]
B -- "yes" --> D{"switch on?"}
D -- "off" --> C
D -- "on" --> E{"safely<br/>rewritable?"}
E -- "no: subshell, eval,<br/>heredoc, backticks" --> F["deny with guidance,<br/>nothing runs"]
E -- "yes" --> G["run trash -v, deny the<br/>original, report targets"]
Intercepted calls are denied and re-executed as trash by the guard itself, so quoting and globs survive:
[dsh-safe-delete] intercepted `rm` — the targets were MOVED TO TRASH (recoverable),
not deleted. Original command denied. Targets: build/ dist
trash: build/ → .Trash/build/
Plain non-rm commands pass through untouched; commands that merely mention rm (echo rm, grep "rm " log) are ignored. rm flags (-f, -r, …) are stripped rather than honored: trash moves whole directories natively.
Scope and limits
| Covered | Not covered | |
|---|---|---|
| Commands | rm, sudo rm, absolute-path rm, xargs rm — simple and compound |
find -delete, unlink, git clean, language runtimes' own file APIs |
| Guarantee | intercepted at the guard layer, before execution | the guard is an accident-prevention net for the most common destructive verb, not a sandbox |
sudo rm is intercepted before sudo ever runs, but trashing files that require root can still fail — trash errors are reported verbatim.
Install
dsh plugin --profile web add github:NattoCB/dsh-safe-delete
Restart the DSH web process — host-side bundles and their patches load at process start. On boot the plugin logs rm guard active once.
Configuration
| Surface | How |
|---|---|
| Web GUI | Settings → General → Safe Delete — the switch takes effect on the next bash call, no reload |
| HTTP | GET /safe-delete/config → { "enabled": bool }; POST /safe-delete/config with { "enabled": bool } |
| File | $DSH_HOME/storages/safe-delete.json — { "enabled": bool } |
Default: enabled. A missing or corrupt state file also resolves to enabled — installing the plugin expresses the intent to have the guard, and a corrupt file never silently downgrades protection.
Development
npm test # node --test: lexer, rewrite matrix, guard contract, switch store/API
The lexer/rewriter is exported as exports._internals so tests exercise the real code paths (analyzeCommand, tokenize, splitSegments, makeGuard, ConfigStore, handleConfigRequest).
License
MIT — part of the awesome-dsh-plugin ecosystem.
Links
More in this category
toby-bridges/api-relay-audit★ 884
Runs local security audits of AI API relays and LLM proxies from DeepSeek Harness, producing Markdown reports for prompt injection, model substitution signals, tool-call rewriting, error leakage, stream integrity, and profile-gated Web3 risks.
SeaOf0/dsh-redteam-model★ 716
Authorized-security DSH collection: nine work modes (redteam coordinator, pentest, code audit, binary analysis, attack-defense, AV evasion, incident response, cloud security, CTF solving) and fifteen runtime plugins, managed from a settings page with one-click deploy, install, update and uninstall.
howmp/dsh-pentest★ 609
Authorized pentest mode for DeepSeek Harness — exploration chain, assets and findings with a Web view.
PerryLink/dsh-auto-review★ 233
Second-model auto-review on the approval answerer chain: a read-only reviewer subagent returns structured allow/deny verdicts with reasons, fail-closed by default.
ADWMC/helm-d#helmd★ 225
Single-bundle reverse-engineering and pentest security plugin: first-turn tool narrowing, domain routing, and 33 tools covering APK, web, native binary, protocol, malware and LLM samples — with unpacking, license-bypass and anti-analysis case playbooks, an H-CoT evaluation engine (semantic routing, /hcot command), a web workbench with a ledger-driven tool shelf, an on-disk case workflow (auto-persisted evidence chain, E-numbered validated findings, post-compaction resume), GitHub-based external tool discovery, and 361 on-demand reference docs.
NanmiCoder/dsh-auto-mode★ 164
Adds an Auto permission preset between Workspace Write and Full access: routine work stays in the official workspace-write sandbox while the current session model reviews escalation and destructive calls, granting one exact wider access once, asking when the intent is ambiguous, and denying critical paths.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.