dsh-honey-guard
Verifieddsh-honey-guard · v0.2.2 · MIT · Web UI
Zero-Leak Honey-Token Guard for DeepSeek Harness — 出站把本地密钥替换为结构合法的蜜罐假值,还原走显式工具,日志与统计全程值安全。
Install
dsh plugin add dsh-honey-guard Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
dsh-honey-guard
DeepSeek Harness (DSH) 的蜜罐脱敏插件——在敏感值离开你的机器之前,把它们换成结构合法的假值(Honey-Token),模型、会话文件、日志里见到的全是假货。
它做什么
全自动,装上即生效:插件挂载 DSH 的 agent/pre-step 与 tools/post-execute 事件,对每一条出站消息(用户输入、模型思考、工具调用参数)做模式扫描,命中即替换:
| 检测器 | 识别 |
|---|---|
sk- + 48 位 |
OpenAI / DeepSeek 类 key |
AKIA + 16 位 |
AWS Access Key ID |
ghp_ / github_pat_ |
GitHub token |
Bearer 后长 token |
请求头凭证 |
-----BEGIN PRIVATE KEY----- |
PEM 私钥 |
替换是确定性的:同一会话内同一真实值永远映射到同一蜜罐(模型不会看到两个名字),跨会话不可关联(两份脱敏记录无法被外部比对出用了同一凭证)。蜜罐结构合法——模型拿到 sk- 开头的假 key 不会起疑,只会得到一次正常的认证失败。
显式还原与手动标记
入站自动还原是刻意不做的:还原出的真值下一轮就会被模型再次看到,等于白脱敏。还原与扩展标记走显式工具:
| 工具 | 用途 |
|---|---|
honey_mark |
把检测器认不出的值(内部 token、私有 key 格式)标记为敏感 |
honey_restore |
把蜜罐还原成真实值写回会话记录——用户可见,模型不可见(下一轮重新脱敏) |
honey_stats |
值安全的聚合统计(映射数 / 替换数 / 还原数 / 金丝雀状态) |
honey_log |
会话内翻日志:把落盘记录渲染成按天分组的时间线(见下) |
另有 Canary Trap:每个会话惰性注册一个永不参与替换的"死蜜罐",在其他会话的文本里出现即告警——说明有记录被跨会话搬运。
日志
默认只走 ctx.logger:dsh-desktop 对 info 级没有任何 UI 或文件出口,只有 warn(金丝雀命中、装配失败)会以系统通知弹出。想在机器上留下逐条记录,打开落盘开关:
# ~/.dsh/profiles/desktop/cordis.patch.yml
- id: honey-guard
name: dsh-honey-guard
config:
logFile: true
logFileMaxMb: 5 # 超过这个大小滚一份 .1
之后每次替换都会往 ~/.dsh/honey-guard/substitutions.jsonl 追加一行 JSON:
{"time":"2026-10-27T01:00:00.000Z","surface":"pre-step","total":2,"hits":{"openai_key":1,"custom":1}}
{"time":"2026-10-27T01:00:03.000Z","surface":"tool ops_bash","canary":"AKIA…","sourceScope":"agent-1","currentScope":"agent-2"}
字段只有 surface、类别计数和金丝雀 id——真实值与蜜罐全文都不写,与日志同一条值安全约定。插件启动时另写一行 "surface":"activate",用来证明这一轮它确实被装配上了。目录不可写时落盘静默停用,不影响脱敏本身。
想在日志里看到"换成了哪个蜜罐"(排查"刚才换了哪几个值"很有用),打开 logHoneys:
config:
logFile: true
logHoneys: true # 记录发出的蜜罐(假值);真实值永不落盘
替换记录会多一个 honeys 字段,卡片和 honey_log 都会把蜜罐渲染出来。注意权衡:蜜罐是假值,泄露它不泄露真实凭证,但同时持有日志和会话文件的人可以把两者逐条对上——这就是它默认关闭的原因。
不想离开会话翻文件,直接让模型调 honey_log("看看最近的脱敏记录"),它把日志尾部渲染成按天分组的时间线:
### 🍯 honey-guard 脱敏日志
共 **132** 条记录,显示最近 **20** 条 · `~/.dsh/honey-guard/substitutions.jsonl`
**2026-10-28**
- `14:35:10` 🚨 **金丝雀告警** · tool ops_bash · `AKIA…` agent-1 → agent-2
- `14:32:01` 🔁 **替换 ×2** · pre-step · openai_key ×1,custom ×1
**2026-10-27**
- `22:37:15` ✅ **插件装配**
日志本身就是值安全的,所以这份渲染给模型看也不泄露。没开 logFile 时工具也能用:读到的是历史记录(会标注"当前未开启"),或者提示你如何打开开关。
设置里的日志卡片
桌面端还有一块 UI:打开 设置 → 插件 → dsh-honey-guard,插件卡片上直接渲染同样的时间线(状态点 + 总数 + 手动刷新,最长滚动 50 条)。数据走主进程挂在本地 web server 上的 GET /api/honey-guard/log(仅回环 Host/Origin,防 DNS rebinding),响应就是上面那些值安全字段。headless profile 没有 web 服务,路由自动不挂载,卡片显示"接口不可达"而脱敏本身不受影响。
安装
dsh plugin --profile desktop add "file:<本项目路径>"
或手动放入 profile 的 node_modules 并在 dsh.profile.bundles 登记。构建与校验:
pnpm install
pnpm run check # typecheck + vitest + tsdown build
架构要点
- Admission-time 替换:出站脱敏发生在消息进入会话之前(
agent/pre-step返回的批次即入会内容),因此会话文件从源头就是蜜罐。 - 区间合并替换:检测器区间与手动标记区间先对原文合并(重叠跳过、长值优先),再一次性 cursor 拼接——蜜罐永不进入被扫描文本。
- 每会话独立映射:
WeakMap<agent, scope>按 agent 对象分桶,被回收自动清理;映射表纯内存,不落盘。 - 值安全:日志、统计、审计事件(
honey/restored)均不含真实值或蜜罐值。
License
MIT