dsh-path-lockbox:对 Agent 的文件与分区访问进行单调拒绝

前言

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。

三层执行语义

插件通过三层拦截来确保路径无法被访问:

  1. 单调守卫(Layer ①)
    - 挂载点:ctx.tools.guard()
    - 行为:只返回拒绝理由或无操作,没有 allow 分支。任何后续监听器都无法放行。
    - 全权模式:生效。

  2. 策略层(Layer ②)
    - 挂载点:tools/pre-execute
    - 行为:早期 deny,模型拿到结构化的策略拒绝文案,并附带“这是部署策略”的提示。
    - 全权模式:生效(除非其它插件短路 allow,见 Layer ① 兜底)。

  3. 结果过滤(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。

诚实边界

  1. 命令文本 ≠ 命令语义。 p=sec; cat $p、base64 -d、$(...) 二次求值可以绕过静态提取——这是所有 harness 内插件的共同上限,不是本插件的 bug。
  2. 不经过工具层的读取(宿主技能加载、@文件 引用、附件)不受影响。
  3. 要把“就算完全访问也无法动”做到内核级,必须叠 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。

  1. 面向 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

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜