ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

dsh-purge:它叫 purge,实际在原地改写官方包的 52 个文件——动手前完整指南

dsh-purge:它叫 purge,实际在原地改写官方包的 52 个文件——动手前完整指南

dsh-purge:它叫 purge,实际在原地改写官方包的 52 个文件——动手前完整指南

【免费下载链接】dsh-purgeDeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分项目地址: https://gitcode.com/GitHub_Trending/ds/dsh-purge

dsh-purge 是装在官方 DeepSeek Harness 上的红队评测补丁插件,名字像清洁工具,行为却是改写:点「应用」后它把本机@deepseek-ai官方包里的 52 处文案、策略和逻辑逐条替换。想装可以,先看清它动什么、会卡在哪、卡住了往哪退。

名字是 purge,动作是 rewrite

purge 容易让人以为最坏情况是删错文件,实际它一个字节都不删。README.zh-CN.md「说明」一节的原文:

改动范围是本机@deepseek-ai/*包里的渲染文案、默认策略和执行逻辑,以及用户目录下的覆盖文件与规则集。

「工作原理」的流程图把动作拆开:判定补丁是否已生效 → 未生效则「备份原件为.dshpurge.bak」→「按补丁列表替换对应文件」→ 覆盖 shim → 注入插件内置的加密默认提示词。注意顺序:备份和替换是同一次「应用」动作里的连续两步,替换的目标是宿主正在运行的node_modules,不是某个独立目录。

补丁规模以 release-notes.md 的 1.1.43 记录为准:

The patch list now includes all 52 items, so the total matches the groups.

52 条补丁分散在多个官方包的文件上,当前版本里多条补丁已合并成升级链展示,但 release-notes.md 的 1.1.70 明确写着「Apply 仍打全部补丁」。清洗页的样子长这样,补丁、shim、备份状态都在这一屏上:

开源版还有一条安全边界:攻击任务只放行本机回环和 RFC1918 私网,域名先解析、全部地址都必须是私网或回环才放行。清洗页的「本地靶场」区域会把这点写明,公网服务器登记不进去。

名字里写的是清理,代码里跑的是替换——这两个词的距离,就是全部风险的来源。

点「应用」的写盘链路:先留边车,再换原件

入口有三处等价:清洗页「应用」、聊天/purge apply、命令行dsh-purge --apply。落到代码是 lib/core.js 的applyPatchesAllHosts(1983 行):它先枚举所有要打补丁的宿主安装位置,每处理一个宿主,先调backupAll(1997 行,函数定义在 6161 行)给每个目标文件生成<文件>.dshpurge.bak边车,再逐条执行替换。边车后缀定义在 6035 行:const BAK_SUFFIX = ".dshpurge.bak"。

对你意味着什么:

  • 被触碰的不是一个文件,而是分布在多个官方包里的几十个文件,每次「应用」整批处理。
  • 官方原版的存世份数从此取决于这份边车。你不留快照,机器上只剩插件替你放的那份。
  • 用户自己 patch 过的文件永不建边车(源码注释标注 #43),这类文件出问题没有自动退路,别在上面手改。

边车是替换前的唯一快照,它的可信度取决于你后来愿不愿意用它。

桌面 EXE 多绕一圈:解包 asar、打补丁、再换包

Web 宿主(dsh web)的补丁对象是node_modules,直接写文件。桌面宿主把代码封在app.asar里,「应用」要多走一步:先把 asar 解包,在解包出来的文件上打补丁,再换回resources/app,最后重启。

release-notes.md 1.1.44 的英文原文描述了这个窗口期怎么收口:

Unpackingapp.asarwrites besideresources/appand swaps in only after the unpack finishes. ... If unpacking sticks or that patch round does not finish, the previous directory is put back and the upgrade marker stays for the next start.

先写到旁边、解包完成才换目录,卡住或补丁没写完就把旧目录放回去、标记留到下次启动重试。这是插件内置的原子式交换,但它依赖的是插件的自愈逻辑——升级中断的现场(比如换到一半断电),靠的是这套回退,而不是你手里的任何文件。

解包换包的中途是全链路最短的窗口,也是唯一一处你插不上手的窗口。

同一句「应用」,可能落在两个宿主、两个时点

单看一次点击,写盘范围是清楚的。把时间维度加进来,范围就变了,三件事:

  1. 启动会自动补打。README.zh-CN.md「介绍」表里写着「启动时:自动再检查并应用。npm 升级盖掉node_modules之后不用手改文件」,开关是配置里的autoApplyOnStart(cordis.patch.yml 第 39 行)。npm 升级把官方包整个盖掉后,下次启动插件会自己重打补丁——你没点任何东西,写盘发生了。
  2. 一次动作覆盖多个安装位置。1.1.61 的版本史:「多宿主 Apply:npm-global 与桌面resources/app一并补丁(#72 路径问题)」,一次「应用」同时命中两处安装。
  3. 丢了会自愈重打。1.1.52 的版本史:「有applied.json但宿主又回到 sealed / 找不到插件根时,判定未对齐并自动重打;面板提示「补丁已丢失,请重新应用」。」

再叠上宿主隔离:官方 Web 和桌面 EXE 分开装、分开应用,各用各的$DSH_HOME,README 的原话是「Web 的按钮只动 Web,桌面的只动桌面。不要在一个里面点另一个的应用」。两套宿主意味着两份主目录,备份也必须是两份——你为 Web 留的快照,对桌面那份正在被改的文件没有覆盖关系。

你备份的那份和此刻正被改的那份是不是同一份,核对之前,「已备份」这个说法不成立。

作者自己留下的事故记录

release-notes.md 里有一条条修好的事故,按版本排开:

版本事故
1.1.45下一版(1.1.46)直接点名:Skip 1.45; that version has bugs. Do not install it.
1.1.70Hub 残装给插件加上pluginPackages后 Cordis 一直 pending,宿主直接退出码 1,插件加载链路整个断掉
1.1.23(#38)提示词补丁每次 apply 叠加约 +841 字符、永不收敛,autoApplyOnStart每轮启动再写一层;已膨胀的宿主文件不会自动缩回,要还原边车或重装宿主
1.1.53(#59–#61)点「应用」后无限重启,窗口关了又被反复拉起
1.1.59(#65)宿主路径或旧标记对不上时,误报「清洗没有写进当前宿主」

每一条都对应真实用户踩到的现场,而且全部已经修掉。换句话说,这份记录是幸存者的名单:版本史只收录修好的,没修好的不在任何文档里。备份的价值就在于让任何一版翻车时,你不需要等社区公告。

版本史只记修好的事故,第一批用户踩的是名单之外的。

手够到「应用」之前做的五件事

  1. 核对它认的是哪份主目录。聊天里发/purge status,核对打印出的DSH_HOME是否与你实际启动的宿主一致。为什么:本机常有两份.dsh(Web 与桌面各一份),插件只动它认识的那一份。验证:打印路径对应你正在用的那个端。
  2. 整目录备份主目录。cp -r "$DSH_HOME" "$DSH_HOME.bak-$(date +%Y%m%d)",Web、桌面各做一次。为什么:插件内置边车只覆盖它即将改写的官方文件,rules/里攒的规则集、$DSH_HOME/dsh-purge-backups/skills/之外的自定义技能、改过的prompt-inject.md只有整目录快照兜得住。验证:备份里profiles/、rules/、prompt-inject.md齐全。
  3. 手改 profile 的package.json前先复制一份。为什么:手动安装只在dependencies和dsh.profile.bundles两处追加,README 原话是「只改对应 profile 的package.json,先备份」。验证:改完对照备份,确认只多了两处、逗号完整。
  4. 核对版本搭配。1.1.78 适配 DSH 0.2.1-rc.2(0.2.0 仍可用),0.1.x 要用 1.1.39 及更早。为什么:对不上的补丁会显示「待应用或跳过」,这是保护机制,不是插件坏了。验证:应用后若补丁列表整片跳过,停下核对版本,不要继续点。
  5. 应用后看一行状态。/purge status会输出一行「备份 / backup」,lib/index.js 146 行的逻辑是state.has_backup ? "有 / yes" : "无 / no",应用之后它该从「无」变「有」。顺手确认插件内置的三层备份各管什么:每个目标文件应用前的<文件>.dshpurge.bak(backupAll)、启用规则集前的.dsh-purge-rule.bak(lib/rules.js 第 21 行)、技能保存删除前的整目录快照$DSH_HOME/dsh-purge-backups/skills/(lib/skills.js 第 29 行)。这三层只保插件自己碰过的东西,第 2 步的整目录才是全量兜底。

快照的成本是一次拷贝,缺一次快照的代价是整台宿主按插件版本走。

翻车后往哪退:从一键还原到手动找回

按代价从低到高排:

1. 一键还原。适用条件:补丁已应用、边车还在。入口三处等价——清洗页「还原」、聊天/purge revert、命令行dsh-purge --revert。lib/core.js 的revertAll(6207 行)用备份覆盖回去并删除边车;没有边车时只按补丁痕迹反拆,源码注释(#41)写明底线:「没有 bak 时绝不删除目标」。重复执行幂等,多还原几次不会越还原越糟。失效边界:边车被手动删掉、或被覆盖成新文件后,这条退路降级为「按标记反拆」,覆盖不上的内容回不去。

2. 文件丢失或变空的自动找回。适用条件:正式文件不见了,或被写成空文件。restoreMissingOriginalsFromBak(lib/core.js 6060 行)在启动、还原、应用三个阶段都会跑一遍,把旁边.dshpurge.bak里的原文拷回。官方自升级把宿主文件整体换成新版时,边车不会跟着动,这条找回逻辑仍然有用。

3. 卸载兜底,加手动还原。适用条件:想彻底移除插件。lib/uninstall.js 的顺序是先还原全部补丁、再还原 shim、最后才删注入文件和插件本身;已应用且还原环节报错时,卸载在 235 行直接中止,轮不到「删完才发现回不去」。仓库里 docs/修改文档.md 还留了一套手动兜底:git checkout -- lib/core.js lib/index.js还原插件侧源码,再把.dshpurge.bak复制回对应目标文件(文档里给了完整的Copy-Item示例)。边车也丢了的人,这是最后一道闸。

「没有备份绝不删目标」保住了最后一步,保不住备份丢失之前的每一步。

收尾

dsh-purge 把可逆性写进了机制:写盘前强制建边车、三个阶段自动找回丢失原件、无快照时拒绝删除目标、卸载先还原后拆除。这套设计对「它自己碰过的官方文件」是认真的。但$DSH_HOME里你攒的规则集、技能库和改过的提示词,不在它的备份清单里——这部分的可逆性,取决于点「应用」之前你自己那份整目录快照。插件负责退路,你负责起点。

它替你把退路修好了,但退路的起点在哪,只有你的快照说了算。

【免费下载链接】dsh-purgeDeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分项目地址: https://gitcode.com/GitHub_Trending/ds/dsh-purge

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进