dsh-privacy-gateway

securitytested: passnpmMIT

Redacts secrets, cookies and personal data in every model request at the host process undici dispatcher and restores the placeholders in the reply, so one interception covers every provider, adapters that plugins add included; per-kind actions mask / warn / block, an optional same-shape fake key, re

下载量 / Downloads
1,116
依赖体积 / node_modules
2.9 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-privacy-gateway

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-privacy-gateway

[English](README.en.md) | 简体中文

在宿主进程的 undici 全局 dispatcher 上装一层脱敏网关。出站把模型请求体里的密钥换成占位符,入站把回流里的占位符换回真值。对 agent、adapter、provider 都无感,一处拦截覆盖所有走 fetch() 的 provider,包括插件提供的 adapter。

如果你在用中转站或者在处理敏感信息、线上数据,请务必注意保护信息安全。

安装

# 正式版(npm)
dsh plugin --profile web add dsh-privacy-gateway@latest

# 同一版本的 GitHub Release 附件(预发布也发在这里)
dsh plugin --profile web add https://github.com/xbzbing/dsh-privacy-gateway/releases/download/v0.1.4/dsh-privacy-gateway-0.1.4.tgz

预发布版本号带 -,只发 GitHub Release、不发 npm。仓库不提交 lib/,dsh plugin add github:… 拿到的树加载不了([ADR-0006](docs/adr/0006-distribution-and-build-artifacts.md))。

在默认的 web profile 里首次安装即装即用,无需重启 dsh 实例。通过 dsh web profile 的插件更新功能更新插件时,无需重启 dsh 实例。手动更新时建议先卸载旧版本再安装新版本,这样也不需要重启。

功能

  • 脱敏范围:密钥、token、密码、私钥、cookie、邮箱、手机号、身份证、银行卡、自定义敏感词,各有开关。
  • 动作可选:按 kind 选 mask / warn / block,密钥可换成同形的假 key(shape)。
  • 记录与统计:按天落盘的脱敏记录、统计卡、会话「隐私保护」标签页;记录里只有占位符,没有真值。
  • /privacy 命令:查状态、临时开关、test 预览一段文本会怎样发出。
  • 配置热更新:日常项在插件页上改,下一次调用即生效;脱敏出错时请求不发出。

脱敏范围

kind · 内容 · 开关

API_KEY · OpenAI / Anthropic sk-…、GitHub / GitLab 令牌、Google AIza…、Slack xox…、Stripe、AWS AKIA…、阿里云 LTAI…、腾讯云 AKID…、Hugging Face、Groq、xAI、npm、PyPI、DigitalOcean、SendGrid 等前缀 · secrets

TOKEN · JWT · secrets

PRIVATE_KEY · PEM 私钥块 · secrets

PASSWORD / SECRET · URL 里的密码、名为 password / secret / token 的字段、中文「密码为…」「密钥是…」 · secrets

COOKIE · Cookie / Set-Cookie 头、curl -b、cookies.txt、Playwright storageState、HAR、常见会话 cookie 名(BDUSS、JSESSIONID 等) · secrets

EMAIL / PHONE / ID_CARD / BANK_CARD · 邮箱、大陆手机号、身份证号(校验位)、银行卡号(Luhn) · personal

TERM · 配置里 words 列出的词 · 有词就脱敏

脱敏过的值在请求的其它地方再出现,也按同一个占位符脱敏(finder 记为 known)。同一个 host 重发的历史保持原来的字节,prompt cache 照样命中。

照着试:下面每行都是假值,复制进会话发出去,统计卡的对应记录里就会出现替换后的占位符。记录、统计、日志和 vendorView 副本里都没有原值,只有占位符和首尾几个字符。

sk-proj-Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wY                             → API_KEY
ghp_Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wYQ7RT2W                           → API_KEY
AKIAQ7RT2W9KLM4NP8XZ                                                 → API_KEY
Authorization: Bearer Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wY9f2kLm4pQr7sT  → TOKEN
DB_PASSWORD=Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wY9                        → SECRET
postgres://app:Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wY9@db.internal/x       → PASSWORD
Cookie: BDUSS=Zq7Lr2Vt9mK1Px3aB5cD8eF0gH4jN6wY                       → COOKIE
someone@gmail.com                                                    → EMAIL
13800138000                                                          → PHONE
11010519491231002X                                                   → ID_CARD
  • 中文写法「密码:…」「密钥是 …」和 URL 里的密码记为 {{PASSWORD_p7gqwtns}},和 SECRET 分开记。
  • EMAIL、PHONE、ID_CARD、BANK_CARD 默认不换,打开「脱敏个人信息」才生效。
  • 「自定义敏感词」里的词按词替换,记为 TERM;「永不脱敏的值」和 allow 里的原样发出。
  • 私钥整段一起换:-----BEGIN 到 -----END,或只有开头一段 base64 的截断私钥。
  • 文档域名(example.com、.example)不算邮箱;手机号要 11 位、身份证要过校验位、银行卡要过 Luhn,否则不换。
  • 字段的值是一个文件名时不是密钥:只由文件名的字符组成、且扩展名是已知的文件类型(模型权重 safetensors/gguf/ckpt 等、压缩包、图片音视频、文档数据),原样发出([ADR-0026](docs/adr/0026-file-name-values.md))。
  • 同一个值重复出现,占位符相同。
  • 短于 8 个字符的秘密(abc123、666666、888888 这类口令)不算值:照原样发出,也不进记录。它们随时能被爆破,遮住只是给人一种并不存在的保护;值表本来也不把这么短的值当作已知值([ADR-0031](docs/adr/0031-no-short-or-template-values.md))。
  • 明显是占位写法的值不算值:8 个以上相同字符连排(sk-proj-xxxx…、AKIA0000…),或自带「这是占位」说明(your_api_key、example、changeme、placeholder、dummy、***)。随机 key 出现 8 连排的概率低于十亿分之一,sk_test_… 这种真测试 key 照旧脱敏([ADR-0031](docs/adr/0031-no-short-or-template-values.md))。
  • 加密算法的名字不算值:SCRAM-SHA-512、PBKDF2WithHmacSHA256 这类名字写在规范里、人人可读,遮住什么都不保护,原样发出([ADR-0033](docs/adr/0033-algorithm-names.md))。
  • 键名和值一样脱敏:{"metadata": {"sk-…": …}} 里的键名也换成占位符,回复里再换回来;协议自身的键(model、role、type、name、id 等)、工具定义和工具调用的参数名不动([ADR-0029](docs/adr/0029-mask-json-keys.md))。

界面

插件配置 · 会话「隐私保护」

![插件配置:总开关、脱敏密钥与凭据、个人信息、同形假 key、工具调用外发保护,以及词表、记录、标签页与 provider](docs/assets/screenshots/1-plugin-config.png) · ![会话「隐私保护」标签页:本会话脱敏开关、今日 / 7 天 / 30 天统计、按 kind / finder / host 的分布与最近记录](docs/assets/screenshots/2-privacy-panel.png)

配置

插件页面里本插件那一行的「配置」页上可以直接改日常项:enabled、secrets、personal、shape、toolGuard、maskKeys、words、allow、record、keepDays、recordContext、vendorView、showPanel、excludeProviders。改了即时保存,从下一次模型调用起生效,不用重启([ADR-0021](docs/adr/0021-live-settings.md))。其余项在 profile 的 ~/.dsh/profiles/<profile>/cordis.patch.yml 里改,写在 id: dsh-privacy-gateway 那一行的 config 下;插件包自带的 cordis.patch.yml 升级时会被覆盖,不要改它。

键 · 默认 · 说明

enabled · true · 总开关;关掉后网关仍在,但所有请求原样放行,不还原、不记录

secrets · true · 脱敏密钥、令牌、密码、私钥、cookie

personal · false · 脱敏邮箱、手机号、身份证号、银行卡号

words · [] · 自己的词(项目代号、客户名),按原样换成 TERM 占位符

allow · [] · 永不脱敏的值:整值匹配,不分大小写

actions · {} · 按 kind 选动作:mask(默认,换成占位符)、warn(照发并记一条)、block(整个请求不发)。例:{ PRIVATE_KEY: block, EMAIL: warn }([ADR-0013](docs/adr/0013-actions.md))

maskKeys · true · 读起来像密钥或个人信息的 JSON 键名也换成占位符({"sk-…": …});协议自身的键(model、role、type、name、id 等)、工具定义和工具调用的参数名永不动,否则供应商读不懂请求。关闭后这类键名原样发出([ADR-0029](docs/adr/0029-mask-json-keys.md))

toolGuard · off · 工具调用参数里还原出值、又指向本机以外的 host 时怎么办:off 只计数,warn 告警并记一条,block 这次调用的参数里不还原,工具拿到占位符([ADR-0014](docs/adr/0014-tool-guard.md))

shape · false · 密钥换成同形的假 key(前缀、长度、字符类别不变),而不是 {{…}} 占位符;不足 8 个字符、或含字母数字与 - _ . 以外字符的值仍用占位符;回复里照样还原([ADR-0015](docs/adr/0015-shape.md))

cookieNames · [] · 追加要脱敏的 cookie 名

cookieKeep · ['lang', 'locale', 'theme', 'tz'] · 永不脱敏的 cookie 名

protectEnvBlock · true · <env> … </env> 块原样发出,供会校验它的 provider 使用([ADR-0004](docs/adr/0004-protected-regions.md))

protectTools · true · 请求的 tools 数组原样发出

excludeHosts · [] · 不改写的 host 或 host:port

excludeProviders

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::8,最后更新 2026-11-05

Links

GitHub · Homepage · npm

Same category