它是什么
API Relay Audit 是给第三方 AI API 中转站、镜像、网关或 LLM proxy 做安全探测的工具——针对那个夹在你和模型 provider 之间的服务。仓库主体是一套 Python 审计程序;DSH 那一半只是一个很薄的适配层,它加了一条命令 /relay-audit,把包内的 audit.py 跑在你指定的中转站上。
最需要先说清的一点是:这个插件不会像沙箱或权限层那样让 agent 本身变安全。 它是一个诊断工具:向你指定的中转站发出探测请求,然后写出一份 Markdown 报告。它查三类东西:prompt 侧信号(隐藏注入、指令覆盖、prompt 提取、上下文截断)、响应完整性(工具调用/包安装命令被改写、错误响应泄漏、Anthropic SSE 流异常)、以及模型身份信号(自称身份不符、流内的模型标识、延迟方差、上游 channel 指纹)。
README 对结论的含义说得很直接:它不是安全认证,不替代人工审查;inconclusive 永远不会被折叠成 clean——被拦截或无法判断的探针会原样留在报告里。仓库自己的证据边界还写明:模型用自然语言自称 Qwen、DeepSeek、GPT 或 Claude 只是身份一致性信号,不能单独证明上游 provider 被替换;要下更强的结论,需要 raw response JSON、request id、stream 签名和可复现实验一起支撑。
怎么装、怎么跑
上游文档给出的安装命令是这一条,并且固定到不可变的 release tag:
dsh plugin --profile web add "github:toby-bridges/api-relay-audit#v2.4.0"
# dsh-cc-tui 及其他基于 profile 的兼容客户端
dsh plugin --profile cc-tui add "github:toby-bridges/api-relay-audit#v2.4.0"
README 里写的是 DSH_PLUGIN_REF=v2.4.0 变量形式;v2.4.0 是真实存在的 tag,其分发验证文档记录了它对应的 commit 571b97142c0d22aae305ac2919e45137bc424dcc,本条核查时也没有更新的 tag。README 提醒:除非你有意测试未发布的改动,否则不要用 master。这个 bundle 是预构建好的 JavaScript,没有 prepare 或构建钩子,所以从 Git 安装不需要在 pnpm 的安装期构建白名单里放行。
挂载后,在所有命令兼容的 DSH surface 上都会出现同一条命令(bundle patch 往组装里插入一行 api-relay-audit):
/relay-audit
/relay-audit --connectivity
/relay-audit --profile web3 --fast-context
/relay-audit --url <URL> --model <claude-model> --credential-ref <DSH_CREDENTIAL_REF>
不带参数时,它从你当前的 DSH 线路解析出目标,然后跑完整的 14 步审计。适配层自己接管五个选项——--url、--model、--credential-ref、--output、--transparent-log——其余 token 原样透传给 audit.py,所以审计脚本的 22 个 flag 仍然可用。它拒绝自己这些选项的缩写形式,也直接拒绝 --key 和 --key-env。
还有一道门槛值得注意:被审计的模型必须能识别为 Claude。适配层会检查模型 id,在有 provider 目录时还会检查该模型的 name 与 description;这几个字符串里都没有 “claude” 时,命令直接报错并且不生成报告。中转接口本身可以是 Anthropic 兼容也可以是 OpenAI 兼容——README 的说法是这个插件「不新增模型基线」。
三个档位
audit.py 接受 --profile general|web3|full,默认 general。按脚本自己的参数说明和 README 的查询意图表:
general—— 所有非 Web3 的中转站检查。Web3 注入探针在这个档位被关闭。第 3–6 步覆盖 prompt 注入与提取;第 5、10、13、14 步承载模型替换信号。web3—— 在通用检查之上增加 Web3 专用探针:三条针对私钥、签名交易拒绝、转账指引的 prompt 注入检查。README 说这些探针本身与模型无关,但刻意做成档位开关,以免普通中转站审计被稀释。full—— 全部检查,即 general 加上 Web3。
14 步依次是:基础设施侦察、模型列表、token 注入、prompt 提取、指令冲突、jailbreak、上下文长度、工具调用替换、错误泄漏、流完整性、Web3 注入、基础设施指纹、延迟方差、上游 channel 分类。README 的边界表把每个查询意图对应到具体步骤,并明确要求不要把四类意图压成一句口号。
跑一次到底会发生什么
这是动手前最该弄清楚的部分。
它会用你的 key,向中转站发出真实的、会计费的请求。 没有 dry-run 之类的开关。不同档次的探测规模差别很大:--connectivity 只发两个低 token 请求(一个 /v1/messages,一个 /v1/chat/completions,各 max_tokens: 8),跑完即退出,既不执行 14 步也不产出 LOW/MEDIUM/HIGH 评级。完整审计则是另一个量级——其中包括上下文长度扫描会依次发出越来越长的提示(默认阶梯是 5 万、10 万、20 万、40 万、60 万、80 万字符;--fast-context 缩减为 1 万/5 万/10 万/20 万),而可选的 --aggressive-error-probes 额外加一个 256 KB 的超长上下文探针,CLI 帮助文本自己就写着「可能在使用按量计费的中转站上产生费用」。README 也说明不带参数的默认行为「可能消耗较多 token」,并建议改用 --connectivity 做低成本检查。
它不会改动中转站。 探针是发往消息端点的 POST,加上若干信息性 GET(/、/v1/models,以及一个故意不存在的路径);审计脚本里没有 PUT、PATCH 或 DELETE。本地只写两样东西:Markdown 报告,以及在你显式传入 --transparent-log 时的追加式 JSONL 日志,后者记录每次请求的时间戳、URL、请求与响应的 SHA-256 和状态码。适配层把报告默认写到会话工作区内的 .api-relay-audit/reports/api-relay-audit-<时间戳>-<commandId>.md,而 --output 与 --transparent-log 一旦解析到工作区之外、或经由符号链接逃出工作区,都会被拒绝。
它读取你已经配置好的 DSH 环境。 适配层注入 commands、credentials、subprocess、llm、settings 五个服务。目标解析会回退到当前 provider 已配置的 profile 取 baseURL 与 apiKeyEnv,模型取当前会话 agent 的模型;命令里显式给出的参数优先。三者有任何一个解析不出来,命令会直接告诉缺哪一个,而不是猜。
凭据是怎么处理的
README 在这一点上的说法是这个插件最扎实的部分,适配层源码基本对得上,但有一处例外必须记下来。
适配层按名字解析 DSH Credential,要求非空,然后只通过环境变量 API_RELAY_AUDIT_KEY 把值交给 Python 子进程,实际调用形式是 audit.py --key-env API_RELAY_AUDIT_KEY。命令参数里从不出现 key 的值:原生的 --key 与调用方自带的 --key-env 在解析阶段就被拒绝,/relay-audit 以 recordInput: false 注册,子进程被捕获的 stdout/stderr 里若出现该密钥,会在错误诊断回到会话之前被替换成 [REDACTED]。凭据引用必须是 POSIX 环境变量名,且每次调用只解析一次。
例外在这里:audit.py 内部大多数 HTTP 调用是把 header 通过 --config -(即 stdin)交给 curl 的,脚本注释也写明这正是为了让凭据不出现在命令行里——但有两条传输路径不是这样:curl_raw_request(裸请求,包括错误泄漏探针)和 stream_call(第 10 步流完整性探针)是用 -H "x-api-key: …" 拼 curl 命令行的。在这几步进行期间,key 就存在于 curl 进程自己的参数表里,本机其他能读进程表的进程可以看到。适配层这一侧是谨慎的;这一段在审计脚本内部。同批发布也说明没有遥测:audit.py 不回传任何数据给作者,脚本里出现的外部主机只有你传入的中转站 URL 和文档链接。
运行要求
- Python 3 需在
PATH上,按python3、python、Windows 下py -3的顺序探测。DSH 适配层通过 harness 的 subprocess 服务启动它。 curl—— 独立版audit.py是生成产物,只用 Python 标准库加上curl可执行文件做 HTTP 传输,不需要pip install。- Node 需满足
^22.19.0 || >=24.0.0,来自包的engines字段。 - Harness —— 仓库把 DSH 兼容性声明写在
docs/skill-distribution.md,README 把它作为 DSH 插件的分发说明链接出来:其中写的是「tested with DSH0.1.0-rc.6anddsh-cc-tui0.4.1」。package.json里没有dsh.compatibility块,主 README 本身只提到「DSH Web 与使用官方@deepseek-ai/dsh-commandsregistry 的社区 TUI」,没有钉版本号。 - peer 依赖(
package.json声明):@deepseek-ai/cordis^4.0.1,以及@deepseek-ai/dsh-commands、dsh-credentials、dsh-llm、dsh-settings、dsh-subprocess,全部钉在0.1.0-rc.6。这些是安装要求,不是兼容性承诺。 - 安装期脚本:没有。
package.json的scripts只有test:dsh。仓库的 DSH 验证文档提到,cc-tuiprofile 自己的dsh-cc-tui@0.4.1依赖需要在那个 profile 的 pnpm 构建策略里放行koffi@3.1.5的安装脚本——那是客户端的要求,不是这个 bundle 的。 - 遥测: 文档没有提,审计脚本里也没有找到。README 未说明权限模型;请按「只把你的 key 发给你提供的中转站 URL,除此之外不发」来理解其网络行为。
已知限制
- 一次运行会在中转站上花掉真实的 token,完整跑一遍并不便宜。唯一的低成本模式是
--connectivity,而它只能告诉你中转站在两种协议里是否应答。 - 结论是信号,不是证明。仓库自己的证据边界写明:替换模型的判断需要旁证材料;身份、延迟和 channel 三类检测都被明确标为信号。
- 无法判断的步骤就保持
inconclusive。判断不了的工具不会替你报「安全」。 - 非 Claude 的 DSH 线路按设计被拒绝,因为当前的身份与流完整性基线是 Claude 专用的。如果你的 DSH provider 不是 Claude,除非显式用
--model指定一个 Claude 模型,否则/relay-audit不会运行。 - 上面说的那两条
curl传输路径,会在请求期间把 key 放进 curl 的参数表。 - 仓库自己的验证文档写明:
--connectivity是通过一个最小 DSH 服务 harness 调用的,而不是在任一 UI 里手工输入;它证明的是适配层、子进程组装、两条协议路径和凭据边界,并明确表示不能证明所有交互式渲染路径。 - README 请读者去点 star。本条目的
security字段没有任何独立扫描作为依据,因此记为unverified。
关于 AGPL-3.0,如实说
许可证是 AGPL-3.0-only:GitHub 元数据给出 AGPL-3.0,package.json 写 AGPL-3.0-only,README 的说法一致,没有分歧可报。AGPL 是带网络条款的强 copyleft:如果你修改了这份代码、并让用户通过网络与之交互,你需要向他们提供对应源码。仅在本机自用属于使用而非分发,不触发任何义务。对一个装进 harness 运行的插件来说有两点实际影响:适配层与生成出来的 audit.py 以同一许可证一起分发;独立脚本由 api_relay_audit/ 模块化源码生成,文件头明确写着不要手改。README 说这个许可证选择是刻意的,目的是让经过改造的网络服务部署与它审计的中转站生态遵循同一套源码公开标准。源码里没有任何使用限制,以上也不构成法律意见。
什么时候用它、什么时候不要用
在你打算把一个中转站用于真正在乎的流量之前用它:coding agent 的工作流、agent 会照做的包安装建议、或者任何与钱包沾边的操作。它适合这件事的原因是本地化——key 只发给你自己选的中转站,而不是发给某个第三方测试网站,报告也留在你的工作区里。刚拿到一个新中转站 URL、只想确认它到底答不答得通时,--connectivity 是个合适的冒烟测试。
不要指望它提供持续防护。它只在你调用时运行,一次只审计一个目标,其余 99% 的时间什么都不做。也不要把 LOW RISK 当成健康证明——README 明确说它不为任何中转站颁发安全认证。同样,别随手对按量计费的中转站跑完整审计:先读上面的成本说明,需要便宜一点就加 --fast-context 或跳过某些步骤。
FAQ
跑这个审计要花钱吗?
要,README 也这么说。不带参数跑的是完整审计,「可能消耗较多 token」。--connectivity 是便宜的模式:两个 max_tokens: 8 的请求。成本大头是上下文长度那一步,它会发出越来越长的提示;而 --aggressive-error-probes 会再加一个 256 KB 探针,它自己的帮助文本就提醒了按量计费的风险。
它会改动中转站,或者改动我的项目吗?
不会改动中转站:探针是发往对话端点的 POST 加上几个信息性 GET,全程没有 PUT、PATCH 或 DELETE。本地它只写 Markdown 报告,以及在你要求时才写的追加式 JSONL 透明日志。在 DSH 插件下这两条路径都必须落在当前会话工作区内,所以它不会在你机器别处散落文件。
我的 API Key 去了哪里?
发给你自己指定的中转站,作为探测请求的认证 header。DSH 适配层从 DSH Credentials 里解析出你指定的凭据,用环境变量 API_RELAY_AUDIT_KEY 交给 Python 进程——从不作为命令参数——并且 /relay-audit 注册时关闭了输入记录,所以原始输入不会进会话日志。出错时回传的内容会先脱敏再进入会话。一处例外:audit.py 内有两条传输路径会用 -H 把 key 拼进 curl 命令行,在那几步期间该值存在于 curl 进程的参数表里。
支持哪些 harness 版本?
仓库的 DSH 分发说明写明了兼容性契约:「tested with DSH 0.1.0-rc.6 and dsh-cc-tui 0.4.1」。主 README 只说到 DSH Web 以及「使用官方 @deepseek-ai/dsh-commands registry 的社区 TUI」为止,package.json 里没有 dsh.compatibility 块——它那几个 0.1.0-rc.6 的 peer 钉版是安装要求,不是兼容性承诺。
能用它审计非 Claude 的中转站吗?
按插件默认行为不行。除非解析出的模型 id——或者该模型在 provider 目录里的 name、description——包含 “claude”,适配层会拒绝运行。中转站自己的 API 可以是 Anthropic 兼容也可以是 OpenAI 兼容;Claude 专用的是审计基线本身。你可以显式传 --model 指定一个 Claude 模型,但身份与流完整性检查本来就是按 Claude 形态的响应设计的。
inconclusive 是什么意思?
意思是工具判断不了。README 对此很直接:被拦截的探针、不支持的格式或含糊的响应都不会被当成安全;它会带着该步的其余证据留在报告里,也不会被折成 clean。请读报告的分步章节,而不只是最后那行 LOW/MEDIUM/HIGH。