前言¶
DeepSeek Harness(DSH)运行在宿主进程中,模型通过工具(read/write/edit/grep/glob 等)访问本地文件与目录。当会话开启 danger-full-access(完全访问)时,仅靠工具层权限已无法阻挡 Agent 读取或写入敏感路径。DSH 社区需要一种在工具调用链路中“硬锁”路径的方案,而不仅仅是依赖宿主权限。
下面介绍 thson-xue/dsh-path-lockbox 插件。它通过三层执行语义,在 monotonic guard(单调守卫)层面阻断路径,即使开启了 danger-full-access 也无法绕过。
插件定位¶
dsh-path-lockbox 是一个 DSH 插件,负责把指定的文件、文件夹、硬盘分区对 Agent 彻底锁死。它属于 admin-security 分类。插件名称为 dsh-path-lockbox,MIT 许可证,当前版本 0.1.14。
三层执行语义¶
插件通过三层拦截来确保路径无法被访问:
-
单调守卫(Layer ①)
- 挂载点:ctx.tools.guard()
- 行为:只返回拒绝理由或无操作,没有 allow 分支。任何后续监听器都无法放行。
- 全权模式:生效。 -
策略层(Layer ②)
- 挂载点:tools/pre-execute
- 行为:早期 deny,模型拿到结构化的策略拒绝文案,并附带“这是部署策略”的提示。
- 全权模式:生效(除非其它插件短路 allow,见 Layer ① 兜底)。 -
结果过滤(Layer ③)
- 挂载点:tools/post-execute
- 行为:grep/glob 结果与 shell stdout/stderr 中含锁定路径的行被剔除,不泄露路径是否存在。
- 全权模式:生效。
覆盖的工具与命令¶
插件拦截以下工具的路径参数,以及 bash / pwsh 的 workdir 与命令文本:
- 工具:read / read_image / write / edit / str_replace_editor / grep / glob
- Shell:bash / pwsh 的 workdir 与命令文本(剥引号、剥 ENV= 前缀、跟随 cd、展开 ~、git-bash 盘符映射 /e/x → e:/x)
- 其它插件工具:通过 extraPathArgs / extraCommandArgs 登记
规则语义¶
文件¶
逐个锁定(叶子,无子项设置)。
文件夹¶
索引子文件夹(I)勾选 = 递归锁整棵树- 不勾选 = 只拦对目录本层的操作
硬盘¶
- 盘符级(如
E:/) - 递归 = 整个分区
- 不勾选 = 只拦分区根操作
匹配规则¶
- 同时比较目标路径与所有祖先目录
- 默认大小写不敏感(
matchCase: false;Windows 文件系统大小写不敏感,敏感比较会静默漏规则)
自身规则存储¶
插件自己的规则存储文件($DSH_HOME/path-lockbox.json)自动加入锁定,agent 和用户规则都无法修改它(硬保护)。
安装与启用¶
安装命令:
dsh plugin --profile <profile> add github:<you>/dsh-path-lockbox
lib/ 构建产物随仓库提交,安装不需要构建脚本授权。锁定版本加 #<commit>。
配置与 UI¶
配置文件¶
- 部署默认写在本仓库的
cordis.patch.yml(files/folders/drives三个列表) - 用户在页面上的改动写入
$DSH_HOME/path-lockbox.json(用户层,整段替换同名列表) - 宿主 settings 服务支持 volatile 字段时保存即时生效,不重启
配置示例¶
- insert:
- id: path-lockbox
name: dsh-path-lockbox
config:
files: [{ path: "D:/合同/报价最终版.xlsx" }]
folders: [{ path: "D:/客户资料", recursive: true, watch: true }]
drives: [{ path: "E:/", recursive: true, watch: false }]
matchCase: false
guidance: true
UI 入口¶
界面本体由宿主路由 GET /path-lockbox/ui 提供;三处入口共用同一份页面:
| 入口 | 位置 | 说明 |
|---|---|---|
| 设置 → 文件锁(推荐) | 设置页左侧导航 | 客户端半身注册 settings.section,label 返回中文“文件锁” |
| 插件详情页配置区 | 插件 → dsh-path-lockbox |
plugins.detail.section 槽,只在本插件自己的页面渲染 |
| 直达地址 | GET /path-lockbox/ui |
不依赖任何 slot,永远可用(也是其它入口的兜底) |
卡片功能对应关系¶
| 截图元素 | 本插件实现 |
|---|---|
| 文件夹(F) 列表框 | 每类卡片中的条目列表(含子项/监控状态徽标) |
| 添加(A)… | 文件/文件夹/硬盘选择器(盘符 → 目录逐层进入) |
| 添加自定义(U)… | 手输绝对路径或盘符 |
| 移除(R) | 条目行 ✕ 或“移除”按钮 |
| 立即重扫描(U) | 校验存在性 + 递归枚举文件数/字节数(5000 上限)+ 刷新监控 |
| 重扫描全部(N) | 全部条目重扫描 |
| 索引子文件夹(I) | recursive(文件条目禁用) |
| 尝试监控变化(M) | watch:fs.watch 递归监控锁定路径,事件进环形缓冲(200 条) |
另有只读状态工具 lockbox_status(模型可见)与 GET /path-lockbox/api/events。
诚实边界¶
- 命令文本 ≠ 命令语义。
p=sec; cat $p、base64 -d、$(...)二次求值可以绕过静态提取——这是所有 harness 内插件的共同上限,不是本插件的 bug。 - 不经过工具层的读取(宿主技能加载、
@文件引用、附件)不受影响。 - 要把“就算完全访问也无法动”做到内核级,必须叠 OS 层(Windows):
# 锁目录/分区(deny ACE 优先级最高,管理员进程也会被拒)
icacls "E:\" /deny "$env:USERNAME:(OI)(CI)(F)" /T /C
# 备份原 ACL 以便恢复
icacls "E:\" /save "$env:USERPROFILE\lockbox-e-acl.txt" /T /C
# 解锁
icacls "E:\" /remove:d "$env:USERNAME"
注意:用标准用户跑 dsh,否则 agent 可以 takeown 改回 ACL。
- 面向 dsh
0.2.0-rc.2契约开发。宿主路由 API(webServer.route/connection.requestRejection)与 slot 注入按 file-shield 同代约定实现了多形态兼容探测;如你的 dsh 版本 API 不同,改src/index.js的mountRoute/fenced与src/client.js三处即可,拦截层不依赖它们。
适用场景与注意¶
适合需要严格控制 Agent 对本地文件系统访问的场景,尤其是:
- 需要锁定敏感文档(合同、报价、客户资料)
- 需要锁定整个硬盘分区或整个分区根操作
- 需要在 danger-full-access 会话中仍然保护路径
注意:
- 插件以当前 dsh 进程权限运行,安装前应检查源码与许可证
- 依赖 dsh >=0.2.0-rc.1 <0.3.0-0
- 如需内核级保护,需结合 OS 层 ACL 机制(见“诚实边界”第 3 条)
结语¶
dsh-path-lockbox 通过 monotonic guard、pre-execute 拦截与 post-execute 结果过滤,在工具调用链路中实现了对文件/文件夹/硬盘的严格锁定。日常编辑规则只需通过“设置 → 文件锁”界面即可完成,规则存储在 $DSH_HOME/path-lockbox.json,且自身规则文件也自动加入锁定,形成硬保护。
插件主页:https://www.skillhub.cn/plugins/thson-xue/dsh-path-lockbox
GitHub:https://github.com/thson-xue/dsh-path-lockbox