編集者注

Qintsg/dsh-safe-delete

Safe delete plugin for DeepSeek Harness (DSH): move files to trash / staging area instead of permanent removal, with restore and purge support.

これは DeepSeek Harness(DSH)プラグインです。当サイトは GitHub README、インストール情報、メンテナンス状況、公開セキュリティシグナルをまとめています。

dsh-safe-delete

DeepSeek Harness(DSH)安全删除插件:文件删除时移入回收区而非直接销毁,支持恢复与彻底清除。

通过DeepSeek Harness使用Deepseek V4 Flash 0731开发

English · 更新日志 · 参与贡献 · 开源协议

功能特性

  • 安全删除:文件/目录移入回收区(.dsh-trash/)而非永久删除。
  • 恢复:将已"删除"的文件恢复到原路径,支持 rename / skip / overwrite 三种冲突策略。
  • 彻底清除:永久清空回收区内容——任何清除操作都需经过审批确认。
  • 删除命令劫持:经 tools/pre-execute 钩子拦截 bash/pwsh 中的 rm / Remove-Item,引导模型改用 safe_deletessh / scp 等远程执行命令完全放行,不做拦截。
  • 超大文件容量保护:删除目标总大小超过回收区上限(maxSizeBytes,默认 5 GiB)时——非 full access 会话需审批;full access 会话需 DSH_FORCE_DELETE=1 才放行永久删除,否则拦截并提示。
  • 无工作区兜底:未分组/无工作区会话回退到全局回收区 $DSH_HOME/.dsh-safe-delete-trash
  • i18n 设置卡片:DSH Web → 设置 → 插件中的配置卡片,文案跟随 DSH 语言(中/英),修改即实时生效。
  • 人类友好回收区files/ 镜像原始目录结构,任何人都可以直接拖回文件。

安装

pnpm add dsh-safe-delete

在 DSH 组合配置中注册插件:

plugins:
  dsh-safe-delete:
    $include: node_modules/dsh-safe-delete/lib/index.js

使用说明

插件注册四个 agent 工具:

工具说明
safe_delete将路径移入回收区(可恢复)。目录需 recursive: truepermanent: true 时直接真删(需审批)。
trash_list列出回收区条目,可按 pattern(如 *.tmp)过滤。
restoreidspattern 恢复到原路径。onConflictrename(默认)/ skip / overwrite
purge永久清除回收区条目(idsall: true)——始终需审批。

系统提示词会引导模型优先使用 safe_delete 而非 rm / Remove-Item

逃生舱(防阻断)

deleteHijack: block 拦截删除命令时,模型仍可明确执行永久删除:

# bash — 强制标记绕过劫持
DSH_FORCE_DELETE=1 rm -rf node_modules

# pwsh
$env:DSH_FORCE_DELETE=1; Remove-Item -Recurse -Force node_modules

或走结构化路径:safe_deletepermanent: true。两条路径仍须审批—— 逃生舱绕过的只是回收区,不是确认环节。

远程命令放行

ssh / scp 等远程执行客户端完全放行,不做删除拦截——远程删除 发生在远端主机,由远端自行管理,本地劫持不干预:

# 以下远程删除均不拦截(无论引号包裹还是裸命令)
ssh user@host "rm -rf /var/www"
ssh user@host rm -rf /var/www

注意:命令文本中出现 ssh / scp 字样的命令会被整体放行(词边界 匹配);引号内的 ssh 字样(如 echo "use ssh")不构成远程命令。

超大文件容量保护

删除目标总大小超过回收区容量上限(maxSizeBytes,默认 5 GiB)时, 为保护回收区不被撑爆,按会话权限执行独立策略:

会话权限行为
非 full access(受限)转人工审批(批准后放行永久删除/移入回收区)
full access + DSH_FORCE_DELETE=1直接放行(永久删除,跳过回收区)
full access 无标记拦截并提示(引导加标记、调大 maxSizeBytes 或使用 safe_delete

safe_delete 工具同样受保护:超大文件默认不允许无声撑爆回收区—— 非 full access 需审批;full access 拒绝移入回收区并提示(可用 permanent: true 永久删除,或调整 maxSizeBytes)。

目标大小的判定为启发式(解析命令路径 + 递归估算),管道/变量拼接等 复杂命令可能漏检,不构成安全边界。

检测局限:劫持是命令文本级启发式——删除命令写在脚本文件内部 (如 clean.sh 里的 rmclean.ps1 里的 Remove-Item、Node/Python 脚本里的删除 API)再执行脚本时,命令文本不含删除关键字,不会被 拦截。系统提示词会引导模型优先使用 safe_delete、不把删除写进脚本。

回收区结构

回收区位置三级解析:显式 trashDir → 工作区 .dsh-trash → 全局 $DSH_HOME/.dsh-safe-delete-trash(未分组/无工作区会话)。

.dsh-trash/                          # 默认回收区(会话工作区下)
├── files/                           # 人类可读:镜像原始路径
│   ├── src/index.ts                 # 首次删除
│   ├── src/index.ts.20260813T223045 # 同名再次删除(时间戳后缀)
│   └── _external/<id>-<name>/       # 工作区外的文件
├── entries/<id>.json                # 条目元数据
├── manifest.jsonl                   # 索引(可由 entries/ 重建)
└── README.md                        # 人工找回指引

手动找回:直接打开 files/ 把文件拖回原位置即可,无需任何工具。

配置项

全部选项可在 DSH Web → 设置 → 插件 → 安全删除 中实时修改(卡片文案跟随 DSH 语言)。

配置类型默认说明
trashDirstring''(工作区 .dsh-trash;无工作区时 $DSH_HOME/.dsh-safe-delete-trash回收区根目录;设置时须为绝对路径
retentionDaysnumber30超过该天数的条目自动清理;0 关闭
maxSizeBytesnumber5368709120(5 GiB)回收区大小上限;删除目标超过该值时触发容量保护(按权限审批/拦截);0 关闭
confirmThresholdnumber10单次删除达到该条数需审批;0 始终确认
restoreConflictenumrename恢复冲突默认策略:rename / skip / overwrite
deleteHijackenumblock劫持 bash/pwsh 删除命令:block / ask / offssh/scp 远程命令始终放行)
interceptFsDeletebooleanfalse预留:拦截未来 ctx.fs 删除方法

开发

pnpm install       # 安装依赖
pnpm test          # 运行单元测试(vitest)
pnpm lint          # 运行 oxlint
pnpm build         # 编译 host 与 client 双端到 lib/
pnpm typecheck     # 类型检查(host 与 client 双端)

项目结构

dsh-safe-delete/
├── src/
│   ├── index.ts        # 插件入口(工具/劫持/settings 接线/路由安装)
│   ├── config.ts       # 配置 schema
│   ├── settings-route.ts # 设置卡片后端路由(GET 快照 / POST 保存)
│   ├── hijack.ts       # 删除命令检测(tools/pre-execute)
│   ├── approval.ts     # 审批门禁(ctx.approval)
│   ├── trash/          # paths / manifest / move / ops(纯逻辑)
│   ├── tools/          # safe_delete / trash_list / restore / purge
│   └── client/         # 浏览器半区:设置卡片 + i18n
├── scripts/build-client.mjs  # client 打包(ModuleLoader 包装)
├── tests/              # 单元测试(vitest)
├── docs/design.md      # 设计文档
├── docs/releasing.md   # 发版指南(OIDC 发布)
└── examples/           # 组合配置示例

发版

版本发布经 GitHub Actions + npm trusted publishing(OIDC)全自动完成—— 无需 token、无需 OTP。详见 docs/releasing.md

开源协议

Apache-2.0 © Qintsg

REPOSITORY SIGNALS

セキュリティとインストールエビデンス

このスコアは公開リポジトリメタデータと当サイトに登録されたインストールエビデンスのみに基づくもので、コードセキュリティ監査とは異なります。

出所の追跡可能性

公開プラグインカタログから取得し、公開 GitHub リポジトリにリンクしています。

ライセンス

リポジトリは Apache-2.0 ライセンスを宣言しています。

メンテナンス活動

過去180日以内にコードの更新があります。

インストールエビデンス

再現可能な正確なインストールメタデータはまだ登録されていません。リポジトリの説明に従って手動で確認してください。

インストールライフサイクルスクリプト

確認したパッケージメタデータにインストールライフサイクルスクリプトは宣言されていません。