前言¶
在 DeepSeek Harness(DSH)里跑智能体时,用户输入、系统提示、工作区说明、会话召回、工具读文件结果等,都会进入发往模型提供商的请求。若其中带有邮箱、电话、API Key 或银行卡号,这些内容会离开本机。常见做法是事后审查日志,或在 Hook 里追加提示,但 DSH 的 Claude Code / Codex Hook 协议里,updatedInput 被文档标明为「解析但不生效」,无法改写即将发送的 prompt 与工具结果。原生 Cordis 插件则可以在 agent loop 入口把检测到的 PII 换成占位符,再交给上游模型。
下面介绍社区插件 dsh-pii-anonymizer(维护者 JWE24-code,分类 admin-security):在 agent loop 起点对「发往模型的一切文本」做确定性、单向的 PII 匿名化,检测靠固定规则与校验和,不调用模型。
这是什么¶
dsh-pii-anonymizer 是 DSH 原生 bundle 插件(npm 包名 dsh-pii-anonymizer,当前版本 0.2.1,MIT 许可证)。它在请求离开本机前,用规则检测结构化 PII,并替换为形如 [[EMAIL_3f9a2c1d]] 的键控占位符;本地会话日志仍按你输入的原样记录,磁盘上的文件与工具输出内容本身不会被插件改写。
挂载位置与改写范围¶
各监听器以 prepend: true 注册,位于对应 waterfall 最外层,在其他插件贡献之后再改写最终文本。
| Hook | 包 | 改写对象 |
|---|---|---|
system-prompt/assemble |
dsh-system-prompt |
提示词 section、runtime context、字符串型 prompt 变量 |
agent/pre-step |
dsh-agent-loop |
本步进入模型的每条消息文本块(用户 prompt、快照、AGENTS.md、recall、relay、技能目录、工具附带 context 等) |
tools/post-execute |
dsh-tools |
模型读到的工具结果 content、块决策反馈及附带 context |
README 说明:外部 Hook 桥接无法实现同等覆盖,只有原生插件能替换进入模型请求的消息、prompt 与工具结果。
检测类型与占位符¶
检测是确定性的:语法或校验和,不用 ML/NER。自由文本姓名、邮编地址等上下文相关 PII intentionally 不检测,以避免误报。
| 类型 | 触发条件 | 校验 |
|---|---|---|
API_KEY |
sk-、sk-ant-、AKIA…、ghp_… 等已知前缀 |
— |
IBAN |
CC00… 等形式 |
mod-97 |
CREDIT_CARD |
13–19 位数字(可含空格/横线) | Luhn |
SSN |
DDD-DD-DDDD |
— |
EMAIL |
RFC 风格地址 | — |
IPV4 / IPV6 |
地址形态 | IPv4 八位范围 |
PHONE |
7–15 位数字及常见分隔符 | 排除 ISO 日期、版本号等 |
占位符格式为 [[TYPE_<hash>]],<hash> 为 HMAC-SHA256(密钥, type + 归一化值) 的前 8 位十六进制。同一真实值在跨会话、子 agent、重启后占位符一致;插件不保存「值→占位符」映射表,单向,无法从插件侧还原明文。
密钥默认写在 $DSH_HOME/pii-anonymizer.key(即 ~/.dsh/pii-anonymizer.key),首次使用生成 32 随机字节、权限 0600。删除密钥文件会导致此后占位符全部变化;若无法读写密钥文件,会退化为进程内密钥,替换仍发生但跨重启不稳定。
行为示例¶
你在对话里输入带 PII 的句子时,模型侧看到的是占位符,并可能收到一条 user 角色的通知(仅类型与数量,不含真实值或占位符字符串)。本地 transcript 仍保留原文。README 中的示意:
you type: email a@x.com or call +31 6 1234 5678
model sees: email [[EMAIL_6c1f0a9e]] or call [[PHONE_d24b7c03]]
+ notice(PII shield: 2 item(s)...)
local log: 按你输入的原样
关闭通知可在配置中设置 notify: false。
覆盖与不覆盖¶
会改写(面向模型的文本):用户 prompt 与本步所有注入消息;system prompt 与 runtime context;经 tools/post-execute 的工具结果正文(含工具体返回的错误)。
不会改写:本地 session log、transcript、memory 与磁盘文件中的明文;complete: true 的 system-prompt section(assemble 之后被框架恢复);工具 schema;跳过 post-execute 的少数工具结果路径;助手回复本身(占位符也不会在输出里被还原)。未纳入检测规则的 PII(如姓名、地址)仍会原样发出。
若工作区说明里的 IP 等字段必须让模型看见,可关闭部分通道:systemPrompt: false 或 toolResults: false。
安装与启用¶
包为 DSH bundle:package.json 声明 dsh.bundle.patch,cordis.patch.yml 插入 pii-anonymizer 行;profile 需在 dependencies 与 dsh.profile.bundles 中同时列出。
在 profile 目录(如 ~/.dsh/profiles/<name>)安装:
npm install dsh-pii-anonymizer
或在终端应用内:
/plugins add dsh-pii-anonymizer
本地 checkout 可用 node tools/register-profile.mjs ~/.dsh/profiles/tui 改 manifest(会写 package.json.bak),并需让 profile 能解析到包,例如:
ln -s "$PWD" ~/.dsh/profiles/node_modules/dsh-pii-anonymizer
安装后重启 DSH 应用加载插件;回滚可恢复对应 profile 的 package.json.bak。
运行环境要求 Node.js >= 20(见 package.json engines)。
配置¶
在 profile 的 Cordis 配置中为插件 id pii-anonymizer 设置:
- id: pii-anonymizer
name: dsh-pii-anonymizer
config:
enabled: true # 总开关
notify: true # 本步输入含 PII 时插入通知消息
debug: false # 仅记录计数类 shield 事件,不记录值
systemPrompt: true # 改写 system prompt + runtime context
toolResults: true # 改写工具结果 content
keyFile: '' # 空则使用 $DSH_HOME/pii-anonymizer.key
适用场景与注意¶
适合在 DSH 日常开发、调试或自动化 agent 中,降低邮箱、密钥、卡号等结构化敏感信息进入第三方模型请求的概率,同时希望在多轮对话里保持同一占位符语义(例如写入 memory 的 [[EMAIL_…]] 仍指同一地址)。
使用前请自行阅读仓库源码与 MIT 许可证;插件以当前 DSH 进程权限运行,本地明文仍存在于 $DSH_HOME 与 workspace 文件中,防护边界是「出站请求」而非全盘加密或 DLP。社区目录 SkillHub 插件页 与 GitHub 仓库由社区维护,与 DeepSeek / 幻方无官方从属关系;DSH 生态本身是「一切皆插件」,安装第三方 bundle 前核对来源与配置是常规做法。
结尾¶
dsh-pii-anonymizer 在 agent loop 最早阶段对发往模型的 prompt、上下文与工具结果做规则化 PII 替换,键控占位符跨会话稳定且不可逆,补上了外部 Hook 无法改写输入的缺口。详情与端到端测试说明见 GitHub:JWE24-code/dsh-pii-anonymizer,目录索引见 SkillHub。