前言¶
DeepSeek Harness(DSH)桌面端通过浏览器 Cookie 做 Web UI 认证。每次启动往往会换一个新端口,Cookie 名会随 host:port 变化而变,旧 Cookie 在浏览器里会保留约 30 天,而 DSH 本身不会主动清理。时间一长,同一 127.0.0.1 下会堆出大量 dsh-auth-*,浏览器把它们全部塞进 Cookie 请求头;当累计超过 Node 默认的 16 KiB maxHeaderSize 时,服务器在进入业务逻辑前就返回 431 Request Header Fields Too Large,连清理代码都跑不到,表现为 Web UI「永久打不开」。手动清浏览器 Cookie 能救一次,但无法从根上阻止再次累积。下面介绍社区插件 dsh-cookie-guard(维护者 bigfatdsh,MIT),它作为客户端类 DSH 插件,在 Web 服务器最前面接管大请求头并下发删除指令,把问题压回可控范围。
这是什么¶
dsh-cookie-guard 是安装在 DSH profile 上的宿主机插件,不修改 DSH 源码,也不依赖第三方 npm 包。插件 id 为 cookie-guard,bundle 名为 dsh-cookie-guard。它针对的是:DSH 浏览器认证 Cookie 名形如 dsh-auth-<sha256(host:port) 的 base64url>,只增不清,最终撑爆请求头。仓库与说明见 GitHub,社区目录页:SkillHub 插件页。
问题是怎么发生的¶
DSH 每次桌面启动常用新端口,浏览器会多写一条新的 dsh-auth-*;旧条目在有效期内一直存在。浏览器对同一 host 发送全部 Cookie,Node 侧默认 maxHeaderSize 为 16 KiB。超过后任意请求(包括首页)都会在监听器之前被 431 拒绝。README 中修复前本机实测示例:
GET / Cookie: big=<20 KB> -> 431 Request Header Fields Too Large
此时即便插件逻辑写在 DSH 里,也进不了 JS 处理器,所以单靠「等 DSH 自己删 Cookie」无法从已爆头的状态恢复。
核心功能¶
安装到当前 desktop profile 后,在同一台正在运行的 GUI 上,README 给出了修复前后对比(节选):
| 场景 | 修复前 | 修复后 |
|---|---|---|
| 20 KB 无效 Cookie | 431 | 401(正常进入认证流程) |
| 约 20 KB Cookie、90 条旧登录 Cookie | 431 | 200,响应中含 87 条删除指令 |
| 约 34 KB Cookie、150 条旧登录 Cookie | 431 | 200,响应中含 147 条删除指令 |
| 当前实例的有效 Cookie | 200 | 200,且不会被误删 |
34 KB 场景下,当前有效 Cookie 保留,其余旧 Cookie 通过 Set-Cookie 带 Max-Age=0 删除;请求头可从约 34 KB 降到约 1 KB。
原理上,插件在 webServer 请求链最前面 prependListener,大致四步:
- 把监听器的
maxHeaderSize提高到可配置上限(默认 256 KiB),让已超过 16 KiB 的请求能进入 JS。 - 用与 DSH 相同的算法算出当前 authority 的 Cookie 名,从
req.headers.cookie里剥掉其它dsh-auth-*,认证代码只看到当前实例的 Cookie。 - 对过期、签名无效、或超出「当前 + 保留条数」预算的 Cookie,在响应里追加删除头(
HttpOnly、SameSite=Strict等与 DSH 一致)。 - 注入方式兼容
writeHead、setHeader、隐式end(),不覆盖 DSH 刚签发的 Cookie。
默认除当前实例外最多保留 3 条其它端口的有效 Cookie,便于多开;只跑单实例时可把保留数设为 0,代价是其它窗口下次请求可能掉登录,需重新走 token URL。
安装与启用¶
从 GitHub 安装(命令来自仓库 README):
dsh plugin add https://github.com/bigfatdsh/dsh-cookie-guard
README 说明:desktop profile 可通过插件管理器安装后,依赖形如 dsh-cookie-guard: link:...,并出现在 dsh.profile.bundles 中。插件以 link: 软链形式存在时,改本目录源码后重启 DSH 即生效。
其它 profile(例如 web)需在该 profile 目录手动 pnpm add link:<本机 dsh-cookie-guard 路径>,并把 "dsh-cookie-guard" 写入该 profile package.json 的 dsh.profile.bundles 数组,再重启 DSH。README 中的示例路径为作者本机路径,你应换成自己机器上的实际路径。
配置¶
可在 bundle 的 cordis.patch.yml(或 profile patch)里覆盖:
- insert:
- id: cookie-guard
name: dsh-cookie-guard
config:
maxHeaderBytes: 262144
keepOtherCookies: 3
cookieBudgetBytes: 4096
| 键 | 默认 | 说明 |
|---|---|---|
maxHeaderBytes |
262144 |
监听器 maxHeaderSize;须大于 16 KiB,范围 16 KiB–1 MiB。 |
keepOtherCookies |
3 |
除当前实例外,最多保留几条其它实例有效 Cookie,范围 0–8。 |
cookieBudgetBytes |
4096 |
认证 Cookie 总预算,超出从最旧删,范围 256 B–16 KiB。 |
典型用法与验证¶
单元测试(README 称 22 项,含大请求头、多 Cookie、401 等):
cd adapted/dsh-cookie-guard
node --test
路径以你本机克隆或 link 的插件目录为准。
对运行中的 GUI 做无副作用探测(把端口换成当前 DSH Web 端口):
python3 - <<'PY'
import urllib.request, urllib.error
req = urllib.request.Request(
"http://127.0.0.1:51302/",
headers={"Cookie": "big=" + "a" * 20000},
)
try:
print(urllib.request.urlopen(req, timeout=5).status)
except urllib.error.HTTPError as e:
print(e.code, e.reason)
PY
安装插件后应看到 401 Unauthorized;未修复时为 431 Request Header Fields Too Large。
适用场景与注意¶
适合长期用 DSH 桌面端、频繁重启或多开端口,且曾在浏览器里堆出大量 127.0.0.1 登录 Cookie 的开发者。插件与 DSH 同进程权限运行,安装前建议阅读 仓库源码 与 MIT 许可证,确认符合你的安全策略。
边界事项(来自 README):
- 删除依赖浏览器执行标准
Set-Cookie过期语义;若个别环境不执行删除,提高后的头部上限仍可能让 UI 可用,旧 Cookie 最迟约 30 天过期。 - 若历史 Cookie 已超过默认 256 KiB 上限,可把
maxHeaderBytes调到1048576后重启;仍不行时需在浏览器 DevTools 中清一次127.0.0.1站点 Cookie,之后由插件接管。 - 上游若改为稳定 Cookie 名,插件仍会保留「提高头部上限 + 清理旧 Cookie」的保险作用,README 认为不会与上游冲突。
回滚:用插件管理器移除 bundle,或在 profile 目录从 package.json 去掉依赖与 bundles 条目后 pnpm install 并重启 DSH。移除后 16 KiB 默认上限恢复,累积问题会再次出现。
DSH 生态强调「一切皆插件」;SkillHub 等社区目录独立于 DeepSeek / 幻方,并非官方应用商店。
结尾¶
dsh-cookie-guard 用监听器前置处理把「431 永久打不开」变成可进入认证或自动下发删除指令的正常路径,并对多开场景保留有限条其它实例 Cookie。需要安装命令与配置细节时,以 GitHub README 为准;浏览插件元信息可打开 SkillHub 目录页。