develku/claude-web-safety-hooks

GitHub: develku/claude-web-safety-hooks

该插件为 Claude Code 提供多层 hooks,拦截并净化来自网页抓取的 prompt injection 攻击,防止恶意指令操纵 AI 行为。

Stars: 0 | Forks: 0

Claude Web Safety Hooks

# Claude Web 安全

tests

为 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 设计的深度防御 hooks,旨在防范**源自网页内容的 prompt injection**。以 Claude Code 插件形式分发。 当 Claude Code 抓取网页或进行网络搜索时,返回的内容可能包含旨在操纵 Claude 行为的隐藏指令。这些 hooks 会在抓取前筛查 URL,通过 8 种抗规避视图扫描返回内容中 600 多种注入模式,并在 Claude 读取前精准抹除攻击内容。 ## 工作原理 共有八个层级,详见 [docs/patterns.md](docs/patterns.md): | 层级 | 触发时机 | 功能描述 | |---|---|---| | **1. URL 预筛查** | PreToolUse | 拦截危险协议、SSRF 目标、IP 地址、凭据泄露、开放重定向和高风险 TLD | | **2. 严重度分级扫描器** | PostToolUse | 涵盖高/中/低(HIGH/MEDIUM/LOW)级别的 600+ 模式;8 种抗规避视图(小写、折叠空格、HTML 实体、标点符号、Unicode 同形字、Unicode 空格、标签剥离、URL 解码) | | **3. 内容净化** | PostToolUse | HIGH = 全部抹除;MEDIUM = 逐行精准处理;输出限制在 50KB 以内 | | **4. 跨工具关联与重组** | PostToolUse | 5 分钟窗口;3 个及以上工具被标记则自动将 MEDIUM 升级为 HIGH。**v6.0+ 还能检测分散在多次抓取中的 payload**(`Part 1/3: ignore` + `Part 2/3: previous` + `Part 3/3: instructions` → 重组匹配) | | **5. 结构验证** | PostToolUse | 感知代码块 / YAML / JSON / HTML 代码 / 行内代码 —— 能清除文档片段中类似 `assistant:` 的误报,无需打扰用户 | | **6. 出站数据外泄防护** | PreToolUse (Bash + web-fetch) | 如果在当前会话的最近 5 分钟内被标记为 HIGH 注入,则会升级出站数据流 —— **感知模式**:在提供交互确认的模式下进行交互确认,在 `bypassPermissions`/`auto`/`dontAsk`(确认操作会被运行环境静默丢弃)的模式下实施硬阻断。从而打破 注入→外泄 链。覆盖网络出口 Bash 命令(`curl`/`wget`/`scp`/`rsync`/`ssh`/`nc`/`socat`/`/dev/tcp`/行内 `python -c`/`node -e`,**通过 `dig`/`nslookup` 的 DNS 隧道,以及 `git push`**)**及** web-fetch 工具(在武装状态下抓取非白名单主机 —— 这是最自然的注入后外泄手段)。可通过 `url-allowlist.txt` 设置可信目标,但向白名单主机的*上传*操作不予豁免;紧急停止开关 `WEB_SAFETY_EGRESS_GUARD_DISABLE=1` | | **7. 多代理可见性** | PostToolUse (Agent) + Stop | *在子代理内部*触发扫描器停止将静默该代理 —— 编排器会看到空结果,提示气泡随之消失。v8 版本会将每次子代理终止首先写入 `[PENDING-KILLED]` 账本行,武装 Layer 6,然后分两次解释终止原因:在解析 Agent 调用旁注入事实上下文,以及一个一次性 Stop 闸门,强制 Claude 在本轮结束前告知用户。升级触发计数**按代理单独计算**,因此并行展开的误报噪声不再会大规模误杀整个代理群 | | **8. Bash 抓取扫描** | PostToolUse (Bash) | 通过 Bash 命令(`curl https://…`)获取的网页内容会作为 stdout 返回并绕过 Layer 2–5。路由闸门会**仅针对具备 web-fetch 特征的命令**(curl/wget/aria2c/HTTPie/文本浏览器),将该 stdout 重新送入相同的引擎进行扫描,因此常规的 `cat`/`ls`/`grep` 输出绝不会被扫描。包含检测、停止及 Layer 6 武装;在设计上范围精准 —— 旨在堵死直接抓取命令的 stdout,而非所有 Bash 网络入口 | ## 架构 该插件为纯 shell 实现 —— 无需守护进程,除 `jq`/`perl`/`shasum` 外无其他依赖。`hooks/hooks.json` 将每个脚本挂载到对应的 Claude Code 工具事件上;脚本通过位于 `/tmp` 下按会话划分的文件进行通信。 ``` web-safety/ ├── hooks/hooks.json # wires scripts → tool events (matchers below) ├── scripts/ │ ├── web-safety-approve.sh # Layer 1 — PreToolUse(web) URL pre-screen │ ├── web-safety-scanner.sh # Layers 2–5 — PostToolUse(web) scan + sanitize; arms Layer 6 │ ├── web-safety-egress.sh # Layer 6 — PreToolUse(Bash) outbound exfiltration guard │ ├── web-safety-agent-result.sh # Layer 7 — PostToolUse(Agent) subagent-kill attribution │ ├── web-safety-stop-gate.sh # Layer 7 — Stop one-shot kill surfacing │ ├── web-safety-bash-scan.sh # Layer 8 — PostToolUse(Bash) fetch-output scan gate │ ├── web-safety-verify-context.sh # Layer 5 — structural-verification helper │ ├── web-safety-listctl.sh # backs /web-safety-allow + /web-safety-block │ └── web-safety-report.sh # backs /web-safety-report ├── commands/ # 4 user-invoked slash commands (auto-discovered) ├── tests/ # 7 suites · 283 cases · Linux+macOS CI └── docs/ # patterns.md, tuning.md, design specs ``` ### Hook 挂载方式 | 事件 | 匹配器 | 脚本 | 层级 | |---|---|---|---| | **PreToolUse** | `WebFetch` / `WebSearch` / MCP web 工具 | `web-safety-approve.sh` → `web-safety-egress.sh` | 1, 6 | | **PreToolUse** | `Bash` | `web-safety-egress.sh` | 6 | | **PostToolUse** | `WebFetch` / `WebSearch` / MCP web 工具 | `web-safety-scanner.sh`(10秒超时) | 2–5(并武装 6) | | **PostToolUse** | `Bash` | `web-safety-bash-scan.sh`(10秒超时) | 8(闸门 → 2–5) | | **PostToolUse** | `Task` / `Agent` | `web-safety-agent-result.sh`(5秒超时) | 7 | | **Stop** | — | `web-safety-stop-gate.sh`(5秒超时) | 7 | Layer 6 同样运行在 web 匹配器和 `Bash` 上(自 v7.5.0 起):在武装状态下,对非白名单主机的出站抓取将像 Bash 出口命令一样被升级拦截。自 v8.1.0 起,完全匹配的 `WebSearch` 是唯一的例外 —— 它没有攻击者可控的目标地址(查询会发送给搜索提供商,而不是任意 endpoint),因此在武装状态下会被**降级**:记录为 `[EGRESS-SEARCH-DOWNGRADE]` 而不进行提示。`WebFetch` 和 MCP 抓取/搜索工具仍保持故障关闭(fail-closed)状态。 ### 运行时数据流 Hook 是没有共享内存的短生命周期进程,因此跨步骤的状态存在于基于会话键值(以 `${CLAUDE_SESSION_ID:-$PPID` 为键)的 `/tmp` 文件中,确保各个会话互不影响): ``` fetch requested │ ▼ PreToolUse(web) [Layer 1] approve.sh ── block dangerous URL / pass ──► fetch runs │ ▼ PostToolUse(web) [Layers 2–5] scanner.sh ── scan · sanitize · correlate │ writes ├─► /tmp/web-safety-session--state (hit log → Layer 4 escalation; │ per-agent ...-agent--state in subagents) ├─► /tmp/web-safety-session--fragments (split-payload reassembly → Layer 4) ├─► /tmp/web-safety-session--armed (timestamp, on HIGH or subagent kill → arms Layer 6) └─► web-safety.log [PENDING-KILLED] row (on subagent kill → Layer 7) │ later: a Bash command OR a web fetch ──► PreToolUse(Bash/web) │ reads [Layer 6] egress.sh ───────────────────┘ armed + egress/outbound-fetch + non-allowlisted host → permissionDecision:"ask" subagent resolves in parent ──► PostToolUse(Task|Agent) [Layer 7] agent-result.sh ── fresh [PENDING-KILLED] row for this agentId? → factual additionalContext next to the (empty) result turn about to end ──► Stop [Layer 7] stop-gate.sh ── unsurfaced kill rows? → block ONCE, summarize to user ``` 用户侧的配置和审计文件位于 `~/.claude/hooks/` 下:包括 `url-allowlist.txt`、`url-blocklist.txt`,以及只允许追加的 `web-safety.log`。 ## 安装 ``` /plugin marketplace add develku/claude-web-safety-hooks /plugin install web-safety@develku /reload-plugins ``` 就这样即可。匹配器覆盖了 `WebFetch`、`WebSearch` 以及广泛的 MCP web 工具集(Playwright、Puppeteer、Firecrawl、Exa、Context7、MCP Docker 变体)。 ## 快速开始 ``` # (可选)添加 URL allowlist 以跳过对受信任域名的 soft-block 检查 mkdir -p ~/.claude/hooks echo "github.com" >> ~/.claude/hooks/url-allowlist.txt echo "anthropic.com" >> ~/.claude/hooks/url-allowlist.txt # (可选)添加 URL blocklist echo "malware-distribution.example.com" >> ~/.claude/hooks/url-blocklist.txt # 触发测试 # 询问 Claude:"fetch https://blog.cyberdesserts.com/prompt-injection-attacks/" # 您应该会看到一个桌面通知(macOS 会播放 Basso/Sosumi/Ping 声音,或者 Linux 调用 notify-send # 以相应的 urgency)并且 Claude 会暂停。 # 检查 audit log tail -20 ~/.claude/hooks/web-safety.log ``` 有关环境变量、严重性调优、白名单/黑名单详情以及误报处理流程,请参阅 [docs/tuning.md](docs/tuning.md)。 ## 命令 插件自带四个斜杠命令(安装时自动发现)。全部仅供用户调用(`disable-model-invocation: true`),并通过上述辅助脚本执行: | 命令 | 参数 | 功能 | |---|---|---| | `/web-safety-report` | `[days]` | 审计日志的 Markdown 摘要 —— 按严重性统计、常用工具、常见主机、近期事件。可选天数窗口。只读操作;绝不修改日志。 | | `/web-safety-allow` | `` | 验证并向 `url-allowlist.txt` 追加受信任域名。仅放宽**软**拦截(高风险 TLD、自定义黑名单)—— 硬拦截(SSRF/内部目标、IP、危险协议、URL 中包含凭据)依然有效。 | | `/web-safety-block` | `` | 验证并向 `url-blocklist.txt` 追加域名 —— 在任何抓取之前予以拒绝。 | | `/web-safety-trust` | `` | 验证并向 `url-content-trust.txt` 追加域名 —— 针对**该来源的内容扫描降级**(不停止、不抹除),让您能阅读引用了攻击字符串的安全文章,同时仍记录 `[TRUST-DOWNGRADE]` 并保留 Layer 6 作为托底。与 `allow` 有所不同。 | ## 环境要求 - Claude Code CLI - `jq`, `bash` 3.2+, `perl`, `shasum` - macOS、Linux 或 Windows(用于桌面通知) —— macOS 通过 `osascript`,Linux 通过 `notify-send` (libnotify) 并尽力播放提示音(`canberra-gtk-play`/`paplay`/`pw-play`),Windows 通过 `powershell.exe` 调用 WinRT toast (Git Bash / WSL);检测功能本身不需要这些依赖,可在任何环境下运行 ## 更新日志 详细的各版本说明请见 [CHANGELOG.md](CHANGELOG.md)。近期发布版本: - **8.2.0** — **Layer 8:针对 Bash 抓取的网页内容扫描。** 堵住了一个完全绕过的漏洞:Layer 2-5 的内容扫描器此前仅挂载于 web-fetch 工具,因此通过 Bash 命令拉取的网页内容(`curl https://evil.com`)作为 stdout 返回时并未被扫描。新加入的针对 `Bash` 的 PostToolUse hook(`web-safety-bash-scan.sh`)是一个轻量级的**路由闸门** —— 只有在 `.tool_input.command` 具有 web-fetch 特征时(`web-safety-lib.sh` 中的新函数 `is_fetch_command`:curl/wget/aria2c/HTTPie/文本浏览器,具备 Layer 6 的边界控制),它才会通过*现有的*引擎扫描 stdout,否则直接退出不进行扫描,因此常规的 `cat`/`ls`/`grep` 输出永远不会进入具备阻断能力的扫描器。在此检测到的抓取行为会通过 `continue:false` 终止,并以与 web 路径相同的方式武装 Layer 6 出口防护;逐字 stdin 重放保留了 `agent_id`/`session_id`,使得子代理(Layer 7)和关联(Layer 4)路径的工作方式保持不变。在设计上**范围精准** —— git/pip/npm(payload 落在磁盘上)和 nc/scp/ssh(Layer 6 的管辖范围)不在 v1 范围内;残留缺口(重定向至文件、转换管道、`| bash`)已在 [docs/patterns.md](docs/patterns.md) 中记录。针对 Bash 结果的 `toolResult` 抹除效能尚在探查中 —— 终止与武装是目前的承重底线。Web-fetch 路径在字节层面完全一致。新增 `run-bash-scan-tests.sh` 测试套件 → 24 个用例(现共 7 套 · 283 例)。 - **8.1.0** — **Layer 6 WebSearch 出口降级。** 终止了导致并行网络搜索无法使用的武装窗口 EGRESS-ASK 泛滥:一旦 HIGH 注入武装了 Layer 6,300秒内的所有出站动作都会升级为交互式 `ask`,而 `WebSearch` 占据了其中绝大部分(在触发此改进的事件中,147 次抓取通道询问中有 104 次都是 `WebSearch`,且全部显示为 `url=`)。WebSearch 没有攻击者可控的目的地 —— 它的查询会发送给配置的搜索提供商,而不是任意 endpoint —— 因此升级它只是故障关闭机制的副作用,并不是真正在防范外泄。现在,在武装状态下,完全匹配的 `WebSearch` 会被**降级**:记录一条 `[EGRESS-SEARCH-DOWNGRADE]` 审计行(包含完整查询,剥离控制字符)并推迟执行,而不是弹出提示。`WebFetch`、Bash 出口和 MCP 抓取/搜索工具保持故障关闭状态(精确字符串匹配,无前缀/正则);武装机制保持不变 —— 搜索*结果*中的 HIGH 依然会武装 Layer 6,因此后续的出口动作仍会询问。可接受的残余风险:查询中的 secret 会留在搜索提供商的日志中 —— 带宽极低、受提供商限制、且被记录以供审计。决策基于跨模型 DCA (`20260618T210522`)。出口测试件 → 96 个用例(现共 6 套 · 259 例)。 - **8.0.0** — **Layer 7:多代理可见性。** 修复了静默丢失子代理的事件:在 Task/Agent 子代理内部触发扫描器停止会导致该代理终止,且没有任何幸存的解释(在该环境下 stopReason 没有读取者;提示气泡也会消失)。终止仍是终止 —— 容器零能力限制保持不变 —— 但现在会被记录到 `[PENDING-KILLED]` 审计行(epoch/session/agent/severity 的 k=v 格式,由 `/web-safety-report` 自动展示),并在停止前武装 Layer 6。两个新 hook 会消费账本:`web-safety-agent-result.sh`(针对 `Task|Agent` 的 PostToolUse)在解析为空结果旁注入事实上下文,以便编排器可以在排除被标记来源的情况下重新调度;`web-safety-stop-gate.sh`(Stop,一次性触发,受 `stop_hook_active` 保护)会强制 Claude 在本轮结束前告知用户。升级触发计数现在**按代理单独计算**(`...-agent--state`),因此并行展开的误报噪声不再会大规模误杀整个代理群,且触发计数会在追加时于状态锁下重新计算 —— 修复了读取→决策的竞态条件,此前 N 个并行扫描器都读取到相同的陈旧计数,导致 3 次触发的界限永远无法生效。主会话行为在字节层面完全一致。在 CLI 2.1.169 上探测验证:子代理 hook stdin 中的 `agent_id`/`agent_type`,`tool_response.agentId` 连接键,Stop `decision:"block"`。新增 `run-agent-tests.sh` 测试套件 → 19 个用例(现共 6 套 · 255 例)。 - **7.12.0** — Layer 6 **模式感知强制执行** + 两个新外泄渠道。防护机制此前仅发出 `permissionDecision:"ask"`,运行环境在 `bypassPermissions`/`auto`/`dontAsk` 模式下会*静默丢弃*该指令 —— 因此对于运行在跳过权限模式的用户而言,Layer 6 虽然能检测并记录,但实际上从未真正阻止过外泄。现在它会读取 hook 的 `permission_mode`,并在这些模式下发出强制 `{decision:"block"}`(与 URL 预筛查使用的机制相同,经实测在绕过模式下依然受尊重),同时在 `default`/`acceptEdits`/`plan` 模式下保留交互式 `ask`。渠道覆盖新增 **DNS 隧道(`dig`/`nslookup`/`drill`)和 `git push`** —— 二者都是此前记录在案的规避漏洞 —— 其中向白名单远程仓库的 `git push` 保持豁免,并针对 `git commit -m "…push…"`、`git pull` 以及 `digest`/`prodigy` 子字符串设置了防误报保护。通过 `url-allowlist.txt` 或 `WEB_SAFETY_EGRESS_GUARD_DISABLE=1` 跳过错误拦截。出口测试套件 → 92 个用例(现共 5 套 · 236 例)。 - **7.11.0** — 按来源划分的**内容信任降级**:新增 `url-content-trust.txt` 列表(及 `/web-safety-trust ` 命令),告知扫描器在受信任来源上保持*检测*,但*降级执行动作* —— 不停止、不抹除 —— 这样您就能阅读引用了攻击字符串的安全文章,而不会让扫描器删掉您刚抓取的核心内容。它依然会写入 `[TRUST-DOWNGRADE]` 审计行(由 `/web-safety-report` 展示),依然会将 Layer 6 外泄防护作为托底武装起来,在让疑似需抹除的模式通过时触发非阻断通知,并且刻意不将其计入跨工具升级。区别于 `url-allowlist.txt`(仅限软性 URL 预拦截);硬性 URL 拦截不受影响。新增 `run-trust-tests.sh` 测试套件 → 21 个用例(现共 5 套 · 215 例)。 - **7.10.0** — Windows toast 通知补齐了跨平台功能集:`_notify_windows` 通过 `powershell.exe` 弹出 WinRT toast(根据严重程度 → 映射 `ms-winsoundevent` 提示音),当存在显示设备时,WSL 优先使用发行版内的 `notify-send`。标题/正文作为环境变量传递给 PowerShell(绝不插值进命令中),PowerShell 是权威的清理器 —— 它会在 `LoadXml` 之前剥离非法的 XML 字符和 CR/LF(堵住了当原始控制字符导致 toast 静默失败时的警报抑制 DoS 漏洞),然后再进行 `SecurityElement::Escape` 处理。通知测试套件 → 21 个用例;CI 步骤使用 `pwsh` 对内嵌的 toast PowerShell 进行解析检查。 - **7.9.0** — 桌面通知现已支持跨平台:新增 `web-safety-notify.sh` 分发器,将三个通知位置(扫描器警报、外泄防护、URL 预拦截)路由至 macOS `osascript` 或 Linux `notify-send`(尽力播放提示音),自动检测 macOS/Linux/WSL/Windows,并在没有通知器/显示设备时降级为静默空操作。各平台专属清理取代了仅限 macOS 的引号/反斜杠剥离 —— Linux 采用 `--` 选项注入防护 + Pango 标记转义 + 剥离 C0/DEL 控制字符 —— 且分发器绝不写入 hook 的 JSON stdout。macOS 行为在字节层面完全一致(所有先前测试套件均通过)。新增 `run-notify-tests.sh` 测试套件 → 15 个用例。(Windows toast 将在后续版本中推出。) - **7.8.0** — Emoji 误报治理已通过全量 Unicode emoji 语料库(3,944 个字形)验证:变体选择器检查现在要求连击 ≥2 次(此前只要遇到像 ⚠️ ❤️ 这样带有 `FE0F` 的 emoji 就会触发),零宽字符检查要求与 ASCII 相邻(此前对所有的 ZWJ emoji 都会触发 —— 如家庭、职业、🏳️‍🌈),HIGH 级别标签字符检查会在标记残留物之前通过精确区域代码剥离 3 个真实的细分旗帜(此前英格兰/苏格兰/威尔士旗帜会被*拦截并净化*)。扫描器测试套件 → 53 个用例。 - **7.7.0** — 针对 15 项审查发现的小幅汇总修复:leetspeak 循环现在会报告每一个混淆模式(而非仅报告第一个),升级工具列表使用真实的 `, ` 分隔符渲染,`listctl` 的添加操作具备原子性,`SESSION_STATE` 的修剪受锁保护,且白名单支持末尾不带换行符的条目。 - **7.6.0** — 堵住两个 HIGH 级别的漏报:增强 base64 检测(剥离 CR/LF、降低阈值、对比解码与真实模式)及跨调用重组规避(首尾截取、补全片段捕获、全量 14 类词典)。前缀索引改为按词构建 + 闸门后发现误报风暴,加入了触发去重集合。 - **7.5.0** — Layer 6 现在也保护 **web-fetch** 渠道(武装状态下抓取非白名单主机)并采用共享主机库;具备上传感知能力的白名单(向白名单主机的上传*不再*被豁免)。 - **7.4.0** — 现支持扫描对象形态的 `tool_response`,拓宽了 MCP 工具匹配器,修复了误报问题,并堵住了审计日志→报告的注入漏洞(URL 剥离控制字符,反引号中和)。 - **7.3.0** — 堵住了一个 SSRF 预筛查绕过(通过规范化主机名防范十进制/十六进制/八进制 IP、userinfo、`*.internal`、元数据主机),一个针对大输入的故障开放(输入限制 + 截断提示),一个无效的十六进制 HTML 实体解码,以及一个会自动清除真正 `[INST]` 注入的验证器正则缺陷;测试框架进一步加固。 - **7.2.0** — macOS 通知现在会在正文 + 副标题中显示具体原因(匹配的模式 / 出站命令 / 拦截的 URL),而非通用文本;加固了 osascript 清理器以剥离反斜杠(仅影响显示,检测逻辑不变)。 - **7.1.0** — 基于对抗性压力测试(约 130 个向量)加固 Layer 6:修复了解释器标记规避(`python3 -u -c …`)和路径组件误报(`ls ~/.ssh/`),扩大了覆盖范围(`rsync`, `ssh`, `socat`, `telnet`, `openssl s_client`, `/dev/tcp`);出口测试套件 → 50 个用例。 - **7.0.0** — Layer 6 出站外泄防护:在标记 HIGH 注入后,PreToolUse(`Bash`) hook 将出口流量升级为需要确认,从而打破 注入→外泄 链。 - **6.3.1** — 修复:斜杠命令 `${CLAUDE_PLUGIN_ROOT}` 的大括号替换。 - **6.3.0** — 新增斜杠命令(`/web-safety-report`, `/web-safety-allow`, `/web-safety-block`)+ 跨平台 CI 测试矩阵。 - **6.2.0** — 仅支持基于插件的安装;移除手动安装路径。 - **6.1.1** — 压力测试后修复的同形字字母桥接问题。 - **6.1.0** — 关闭了字母边界及仅限前后缀的限制漏洞。 - **6.0.0** — 跨调用 payload 重组 (E8)。 ## 测试 ``` ./tests/run-tests.sh # scanner — 53 cases ./tests/run-cmd-tests.sh # command helpers — 49 cases ./tests/run-egress-tests.sh # Layer 6 egress guard — 96 cases ./tests/run-notify-tests.sh # cross-platform notification dispatcher — 21 cases ./tests/run-trust-tests.sh # content-trust downgrade — 21 cases ./tests/run-agent-tests.sh # Layer 7 multi-agent visibility — 19 cases ./tests/run-bash-scan-tests.sh # Layer 8 Bash-fetch scan — 24 cases ``` 包含 53 个扫描器用例(涵盖单次抓取 payload + 多次抓取重组序列 + 强制执行 / 大输入 / 性能断言),遍及 HIGH/MEDIUM/LOW/legit/reassembly 分类,覆盖全部 8 种抗规避视图、base64 编码 payload、十六进制/十进制 HTML 实体解码、Layer 5 误报防护、多模式 HIGH 组合、排序 token 重排攻击、跨会话隔离、字母边界与尾部拆分重组、已触发抑制、3 字符前后缀片段、同形字桥接、多技术 leetspeak、emoji 误报防护(变体选择器 / ZWJ / 细分旗帜,已通过全量 3,944 个 Unicode emoji 语料库验证),以及 256 KB 页面的性能预算。第二套测试(`run-cmd-tests.sh`)涵盖了报告及允许/拦截辅助脚本 —— 包括原子/并发列表添加、白名单规范化,以及通过预筛查进行的 SSRF 硬拦截类别。第三套测试(`run-egress-tests.sh`)涵盖了 Layer 6 出站外泄防护中的 **Bash 和 web-fetch 双渠道** —— 涵盖武装状态生成、模式感知强制执行决策(在尊重询问的模式下进行交互式 `ask`,而在 `bypassPermissions`/`auto`/`dontAsk` 模式下强制 `block`,在没有 `permission_mode` 时保持向后兼容的 `ask`)、DNS 隧道(`dig`/`nslookup`)和 `git push` 渠道及其防误报保护、白名单豁免及感知上传的不豁免逻辑、完全匹配的 `WebSearch` 出口降级(武装状态下的 `WebSearch` 仅记录不提示,而非 `WebSearch` 的 MCP 搜索工具则保持故障关闭)、会话隔离,以及路径限定二进制文件的边界情况。第四套测试(`run-notify-tests.sh`)涵盖了跨平台通知分发器 —— 平台检测(macOS/Linux/WSL/Windows)、Linux `--` 选项注入防护、Pango 标记转义及剥离 C0/DEL 控制字符、无头模式(无 DBUS)下的跳过、Windows toast 契约(环境变量传递、控制字符/CRLF 剥离、`ms-winsoundevent` 映射、无 powershell 时的故障安全)以及嘈杂的通知器绝不泄漏到 hook 的 JSON stdout 的硬性不变量。第五套测试(`run-trust-tests.sh`)涵盖了按来源的内容信任降级 —— 即受信任主机的 HIGH/MEDIUM 检测在不被抹除、不被终止的情况下通过,同时依然记录 `[TRUST-DOWNGRADE]` 并武装 Layer 6;涵盖子域名匹配、信任条目绝不全局豁免其他主机、受信任主机上的干净内容不进行任何伪造、降级不污染跨工具升级,以及 `listctl trust` 验证。第六套测试(run-agent-tests.sh`)涵盖了 Layer 7 多代理可见性 —— 即子代理 MEDIUM/ESCALATED 终止会写入 `[PENDING-KILLED]` 账本行并武装 Layer 6,同时主会话路径在字节层面保持完全一致;涵盖按代理升级范围划分(跨代理命中不汇聚;无 `agent_id` 时的会话回退依然触发升级)、并行扫描器下的锁定原子重新计数(两个并发触发中恰好只有一个升级,不丢失行)、归属权 hook 的行→`additionalContext` 连接与会话/新鲜度过滤器,以及 Stop 闸门的一次性及 `stop_hook_active` 契约。第七套测试(`run-bash-scan-tests.sh`)涵盖了 Layer 8 Bash 抓取扫描 —— 即具备抓取特征命令的注入 stdout 会被终止,而非抓取命令(`cat`/`ls`/`grep`)的*相同* stdout 绝不会被扫描(核心路由鉴别器)、`is_fetch_command` 防误报保护(子字符串 `mycurl`、路径组件 `~/.curlrc`、特意排除的 `git pull`,但路径限定的 `/usr/bin/curl` 和加引号的 `'curl'` 依然匹配)、URL 白名单绝不抑制内容扫描、终止机制的模式独立性,以及 Bash 抓取下的子代理终止账本及 Layer 6 武装。这全部七套测试均运行在基于 Linux + macOS 矩阵的 CI 上,此外,`pwsh` 步骤还会对内嵌的 Windows toast PowerShell 进行解析检查(由于目前不存在 Windows 运行器,此举旨在防止语法错误静默破坏 toast)。详见 [tests/README.md](tests/README.md)。 ## 许可证 [MIT](LICENSE)。
标签:AI安全, Chat Copilot, Claude Code, Cutter, DLL 劫持, 大语言模型, 应用安全, 防御机制