DeepSeek Harness Hub
← 返回列表

注入流过滤器XiaoYuOvO/dsh-llm-injection-filter

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

实时拦截模型响应中的提示词注入与污染内容

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/4 · 已提供中文文档

DSH LLM 响应流注入过滤器:在 llm/stream 瀑布流上硬阻断罕见 Unicode 文字系统(Track A)+ 基于评分的处置控制字符 / 协议标记 / 文字系统混用 / 垃圾关键词(Track B)。安装:dsh plugin --profile web add github:XiaoYuOvO/dsh-llm-injection-filter

综合分
29.5
GitHub 分
29.5
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add XiaoYuOvO/dsh-llm-injection-filter
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-llm-injection-filter

DeepSeek Harness 的 LLM 响应流注入过滤器:在模型流式响应进入 agent 之前,实时检测疑似提示词注入 / 污染内容并处置。挂载于 llm/stream waterfall,对所有适配器生效,不改动任何运行时源码。

背景动机(真实安全事件)

一个 coding agent 会话(gpt-5.6-terra / openai / OpenAI Responses API)中,模型在生成 edit 工具的 new_string 参数时,于正常代码之后无缝接续输出了一段注入式载荷并被逐字写入源码、进入 Git 历史。污染样本:

//ฤศจassistant to=functions.edit  彩神争霸网站՞ւjson /*、、](只替换字符串值内部,保持 JSON 引号/结构不变;逐 delta 与 block-end 权威内容同步改写);
- reject:block-end 把命中 tool-call 的 block.arguments 改写为 {"$rejected":"dsh-injection-filter","reason":""}(缺必需字段 → 工具 schema 校验失败 → INVALID_ARGS 返回模型,模型可自我纠正);text 命中替换为 [FILTERED:];reasoning 只 audit。
- 轨道 A 与 B 独立、同时生效;A 命中时不做 strip/reject,直接中断。

配置
js
const CFG = {
enabled: true,                 // 总开关
hardBlockRareScripts: true,    // 轨道 A:罕见脚本 → 直接中断(最高优先级,无视 mode)
allowedScripts: ['Latin', 'Han', 'Common', 'Inherited', 'Greek'], // 允许脚本白名单(含 Greek 放行数学希腊字母);可追加 'Thai'/'Cyrillic' 等放行
checkReasoning: false,         // 是否对 reasoning-delta 也做轨道 A 检测(默认关)
mode: 'audit',                 // 轨道 B:'audit' | 'strip' | 'reject'
minScore: 100,                 // 轨道 B 触发阈值
applyToProviders: [],          // 空 = 全部 provider;可填 ['openai']
applyToModels: [],             // 空 = 全部模型;非空 = 仅检查这些模型(子串/前缀匹配,如 ['gpt-5'])
skipProviders: [],             // 提供商跳过名单:命中即不检查(子串匹配)
skipModels: [],                // 模型跳过名单:命中即不检查
maxRecords: 100,               // 拦截记录环形缓冲上限(设置页可查)
extraKeywords: [],             // 额外关键词
maxScanLen: 16384,             // 轨道 B 单段扫描长度上限
maxSampleLen: 120,             // 审计样本截断长度
recordMaxLen: 8192,            // 中断记录中载荷详情(delta / 已累积 arguments)的截断长度
}

审计日志

每次命中输出一行结构化日志(console.error):

[llm-injection-filter] {"provider":"openai","model":"gpt-5.6-terra","sessionId":"...","callId":"call_1","toolName":"edit","rule":"HARD_BLOCK","mode":"audit","score":210,"detail":{...},"sample":"..."}

rule ∈ HARD_BLOCK | CTRL | PROTO | SCRIPT | KW;只提取标量,sample 截断 ≤ maxSampleLen。

中断时详细记录(RECORD)

轨道 A 命中、需要中断 agent loop 时,除上述紧凑审计行外,额外输出一条结构化 RECORD 行,包含出现问题的请求身份与相应载荷的详细信息(取证用):

[llm-injection-filter][RECORD] {"event":"llm-stream-filtered","code":"RESPONSE_FILTERED","time":"","request":{"provider":"openai","model":"gpt-5.6-terra","sessionId":"...","purpose":"agent-loop"},"block":{"kind":"tool-call-arguments","index":0,"callId":"call_1","toolName":"edit","deltaText":"","deltaLength":,"accumulatedArguments":"","accumulatedLength":},"char":"","charCode":,"script":"Thai","sample":""}

- block.kind ∈ text | tool-call-arguments | reasoning;tool-call 场景额外携带 index/callId/toolName/accumulatedArguments(拦截瞬间的完整载荷,含命中 delta 本身)。
- 载荷详情按 recordMaxLen 截断(deltaLength / accumulatedLength 保留完整长度);只提取标量/有界文本,不触碰 options.messages 等大型 live 对象;不落盘,随插件 fiber 输出到结构化日志通道。

WebUI 设置页(运行时配置)

v1.1.0 起,Web 客户端「设置 → LLM 注入过滤器」整页可实时调整(改动即时生效,无需重启):

- 快捷全局开关:页面顶部总开关(等同 CFG.enabled),可一键暂停全部检测;
- 拦截哪些字符类别:允许脚本白名单 chip 编辑(点击 chip 移除、点击下方候选项/输入框添加,如 Cyrillic)——即 allowedScripts;
- 轨道 A / reasoning / 轨道 B 模式开关与下拉;
- 检查范围:跳过的提供商 / 跳过的模型 / 仅检查这些提供商 / 仅检查这些模型——即 skipProviders、skipModels、applyToProviders、applyToModels(支持子串/前缀);
- 拦截记录查询:列表展示最近 N 条(时间 / provider/model / 工具名 / 脚本 U+ 码点或规则+得分 / 样本 / 原因),可刷新、清空。

架构(三路径中的 Path C + B 混合,免改 harness 白名单):

- 客户端 = settings.section 顶级设置页(lib/client.js,dsh.client 声明 web 平台);状态持久化在 localStorage(dsh-llm-injection-filter.v1);
- Host 侧每次 llm/stream 分派读运行时状态(启动时复制自 CFG 默认值),设置页通过插件私有 fenced 路由读写:GET/POST /api-llm-injection-filter/{state,set,records,clear-records}(webServer.register,首次流触达惰性补挂);记录也存进程内环形缓冲(maxRecords,硬阻断与 reject 都写入)。
- 打开设置页时会自动把 localStorage 里保存的配置应用到 Host;Host 重启后配置回到默认,需在设置页重新保存(localStorage 仍在,页面打开即自动应用)。
- 默认允许集合含 Latin/Han/Common/Inherited/Greek。含 Greek 是为了放行数学表达式中常用的希腊字母(如 U+03B8 角 theta 等),避免合法数学输出被硬阻断(用户实测反馈后加入)。仍不含日文(假名)/韩文(谚文)/俄文(西里尔)等,含这些脚本的合法输出会被硬阻断——这是刻意设计的极端严格语义(宁可误杀,不可放过);逃生门是 allowedScripts 配置(可追加如 'Thai'、'Cyrillic' 放行相应脚本)。
- maxScanLen 只约束轨道 B 的逐段扫描/替换(超出部分原样保留、不处理);轨道 A 不设上限(快筛优先,宁可慢,不可放过)。
- reject 模式依赖 block-end 携带完整 arguments 做整块改写;极少数不发 block-end 的 delta-only 流中 tool-call 参数无法整块改写(原样透传,仅审计)。
- 轨道 A 检测自身绝不抛异常(try/catch 包裹,异常时放行该 delta);规则编译失败在 apply 时即报错并停用该规则。

交付形态

- 动态插件:code.host 即本源码(纯 JS、无 import、顶层常量配置),return { apply, CFG } 收尾;ctx.on('llm/stream', ...) 注册的监听器随插件 fiber 自动清理,停止/卸载零残留(无定时器/全局订阅)。
- npm 包:lib/index.js(本文件)+ package.json,module.exports = { apply, CFG, ... };Node ≥18。

正式安装(web profile,官方 CLI)

包声明了 dsh.bundle.patch(cordis.patch.yml),dsh plugin 的 bundle 协调会自动把它加进
dsh.profile.bundles,下次启动即随 host 组合挂载(对所有会话的 llm/stream 生效)。
powershell
路径含空格需用 8.3 短路径(cmd 批处理转发会吞掉空格段)
dsh plugin --profile web add "link:G:/DEEPSE~1/data/dsh/plugins/LLM-IN~1"
验证:组合树中应出现 id: llm-injection-filter / name: dsh-llm-injection-filter
dsh --profile web --dump-config

安装后:
- profiles\web\package.json → dependencies 增加 "dsh-llm-injection-filter": "link:G:/DEEPSE~1/data/dsh/plugins/LLM-IN~1";
dsh.profile.bundles 末尾自动追加 "dsh-llm-injection-filter"。
- profiles\web\node_modules\dsh-llm-injection-filter → Junction 指向源码目录(改源码即生效,下次重启加载)。
- 重启 DSH 后生效;重启前由会话内动态插件(injf-1)继续覆盖。

从 GitHub 一键安装(推上 GitHub 后)

仓库根目录 = 包根目录(package.json 必须在仓库根)。包无构建脚本、无运行时依赖 →
安装无 allowBuilds 拦截、无 peer 警告。推上公开 GitHub 后,一条命令完成安装 + 挂载:
powershell
默认分支
dsh plugin --profile web add github:XiaoYuOvO/dsh-llm-injection-filter
指定分支/提交/tag(可选)
dsh plugin --profile web add github:XiaoYuOvO/dsh-llm-injection-filter#main
按 tag 安装(推荐,锁定已验证版本)
dsh plugin --profile web add github:XiaoYuOvO/dsh-llm-injection-filter#v1.1.0

原理:dsh plugin 把参数转发给 pnpm(原生支持 github: 规格,走 codeload tarball),
安装后 CLI 的 bundle 协调读取已装包 manifest 的 dsh.bundle.patch 并自动追加到
dsh.profile.bundles——与本地 link: 安装走完全相同的挂载路径(已实证)。

打包约定(重要,勿改回;均经实测验证):
- 不要加回 package.json 的 files 字段——pnpm 的 packlist 语义在 tarball 安装路径下
会因 files(或包内 .npmignore)使 packlist 输出与 tarball 条目数不一致,走重加路径,
可能触发其 parseTarball 的"剥首个路径分量"行为(专为 registry package/... 包裹格式
设计),把未包裹 tarball 里的 lib/index.js 误剥成根 index.js、lib/ 丢失。已实测。
- 根入口 index.js = 双保险:main 指向包根的一行转发(module.exports = require('./lib/index.js')),
即便遇到未包裹 tarball 的路径剥离,真实实现 lib/index.js 也不受影响。勿删除该文件。
- github: 安装本身安全:codeload tarball 天然带 -/ 顶层包裹,pnpm 剥掉
包裹层后 lib/ 结构完好——已用 codeload 同构(包裹式)tarball 实测:lib/index.js、
cordis.patch.yml、README.md、LICENSE、package.json 全部就位,require 正常。
- 发布内容用两层控制:.gitattributes export-ignore(codeload 瘦身,排除 test/、
plugin-body.js、scripts/)+ .npmignore(npm publish 瘦身)。两者都
不得排除 cordis.patch.yml(bundle 挂载声明)。
- 验证脚本:scripts/git-install-test.ps1(git resolver + codeload 等价 tarball +
带 .gitignore 场景)、scripts/codeload-sim-test.ps1(包裹式 tarball)。

前置条件 / 注意:
- 仓库公开,或本机已配置 GitHub 凭据;本机需能访问 github.com(本部署 git 代理
http://127.0.0.1:7800,必要时先配置)。
- 已用 link: 本地装过的机器,再次 add github:... 会替换 dependency spec
(bundles 条目保持不变,不会双挂载)。
- 若之后选择 npm publish(内容由 .npmignore 控制:只含 lib/、cordis.patch.yml、README.md、LICENSE、package.json),
等价命令为 dsh plugin --profile web add dsh-llm-injection-filter@1.1.1。

测试
bash
npm test   # ① test/run-tests.js(33 项,核心过滤逻辑)② test/client-smoke.js(bundle materialize 契约)③ test/client-render-smoke.js(设置页 mini-render + 挂载 effect 执行,防导出变量覆盖同名函数类回归)

端到端(清单 17):挂载后真实模型调用应零延迟零中断;构造含泰文的 delta 时 turn 以 RESPONSE_FILTERED 错误结束、前端会话视图出现错误横幅、llm/retry 事件不产生(以上路径已通过源码核实:dsh-agent-loop step() → agent/request-error → LlmError → turn/end;dsh-llm-retry 默认可重试码不含 RESPONSE_FILTERED)。

客户端加载契约(v1.1.1 修复,勿回退):浏览器 loader(@deepseek-ai/dsh-client-modules)materialize 时
exports = factory(require) 的返回值,factory 作用域内没有 module/exports 全局——lib/client.js 必须
自包含并在结尾 return { inject, apply },不得引用未声明的 module(v1.1.0 因此 ReferenceError 静默加载失败、
设置页不出现;已由 test/client-smoke.js 锁定该契约)。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

同作者(XiaoYuOvO)的其他插件

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群