dsh-pii-anonymizer:在 Agent 环路上对发往模型的文本做确定性 PII 脱敏

前言

在 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。

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

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

小夜