TDharm/ai-context-guard
GitHub: TDharm/ai-context-guard
一个零依赖的轻量扫描器,用于检测 AI 编码助手上下文文件中隐藏的不可见 Unicode 字符,防止恶意指令通过隐形字符注入。
Stars: 1 | Forks: 0
# AI Context Guard
[](https://github.com/TDharm/ai-context-guard/actions/workflows/test.yml)
[](LICENSE)
一个微小且无依赖的扫描器,用于标记你的 AI 编码 agent 读取的上下文文件中的**隐藏字符**,这些文件包括 `CLAUDE.md`、`.cursorrules` 和 `AGENTS.md`。
这些文件会在会话开始时被 Claude Code 和 Cursor 等工具加载,并被视为受信任的指令。攻击者如果能成功篡改其中一个文件,就可以利用在屏幕上不占用可见空间的字符来隐藏指令:零宽度 Unicode、双向控制字符、Unicode "tag" 字符,以及其他不可见或控制码位。人工审查 diff 时什么也看不到。而模型会读取这些字节并照此执行。
该工具能让这些字符变得可见,从而在代码审查中暴露并在 CI 中失败。
它是 The Hidden Layer 上 ["Attackers Are Hiding Instructions Your AI Coding Agent Will Obey"](https://tarkar.substack.com/) 这篇文章的配套工具。
## 它的功能
- 默认扫描 `CLAUDE.md`、`AGENTS.md`、`GEMINI.md`、`.cursorrules`、`.windsurfrules`、`.clinerules`、`.github/copilot-instructions.md`,以及 `.cursor/rules/` 等规则目录。也可以将其指向任何文件或文件夹。
- 标记零宽度字符(例如 U+200B、U+200C、U+200D、U+2060、U+FEFF)、双向控制字符("Trojan Source" 类别,U+202A 到 U+202E 以及 U+2066 到 U+2069)、Unicode tag 字符(U+E0000 到 U+E007F,用于隐藏不可见的 ASCII)、软连字符,以及其他控制和格式码位。
- 报告文件、行、列、码位以及官方 Unicode 名称。
- 发现问题时以非零状态退出,因此可用作 CI 门禁或 pre-commit hook。
- 检测优先:默认情况下不进行任何更改。可选的 `--strip` 模式可在你检查完毕后移除标记的字符,并写入一个 `.bak` 备份。
它检测的是隐藏字符,而不是恶意意图。可见但恶意的指令仍需你通过阅读文件来发现。这缩小了盲区,但并不能取代审查。
## 环境要求
Python 3.8 或更高版本。无需任何第三方包。这就是全部的依赖列表。
## 快速开始
```
git clone https://github.com/TDharm/ai-context-guard.git
cd ai-context-guard
# 查看它捕获中毒文件
python ai_context_guard.py examples/poisoned-CLAUDE.md
# 查看干净文件通过
python ai_context_guard.py examples/clean-CLAUDE.md
```
## 用法
```
# 扫描当前目录下已知的 agent context 文件
python ai_context_guard.py
# 扫描特定文件或文件夹
python ai_context_guard.py CLAUDE.md .cursor/rules/
# 机器可读输出
python ai_context_guard.py --json
# 同时标记 variation selectors(更严格,噪音略多)
python ai_context_guard.py --strict
# 允许您认定合法的 codepoint(例如 emoji joiner)
python ai_context_guard.py --allow 200D,FE0F
# 原地移除被标记的字符,保留 .bak 备份
python ai_context_guard.py --strip CLAUDE.md
```
退出代码:`0` 正常,`1` 发现隐藏字符,`2` 使用或 IO 错误。
## 输出示例
在一个被投毒的上下文文件上运行:
```
ai-context-guard: found 5 hidden character(s) in 1 file(s).
examples/poisoned-CLAUDE.md
line 3, col 20: U+200B ZERO WIDTH SPACE [Cf]
line 3, col 34: U+2060 WORD JOINER [Cf]
line 4, col 12: U+202E RIGHT-TO-LEFT OVERRIDE [Cf]
line 4, col 21: U+202C POP DIRECTIONAL FORMATTING [Cf]
line 5, col 13: U+E0041 TAG LATIN CAPITAL LETTER A [Cf]
These characters are invisible or non-printing in a normal editor and diff.
Review the file, then re-run with --strip to remove them, or --allow
HEX[,HEX...] if a flagged character is legitimate (for example an emoji joiner).
```
## 在 CI 中运行 (GitHub Actions)
将 [`.github/workflows/context-scan.yml`](.github/workflows/context-scan.yml) 复制到你要保护的代码库中。它会在每次 pull request 和 push 时扫描你的 agent 上下文文件,如果发现隐藏字符,则使任务失败。这将把“审查 diff”(无法显示不可见字符)转变为构建过程强制执行的检查。
## 作为 pre-commit hook 运行
如果你使用 [pre-commit](https://pre-commit.com/),请将以下内容添加到你的 `.pre-commit-config.yaml` 中:
```
repos:
- repo: https://github.com/TDharm/ai-context-guard
rev: v0.1.0
hooks:
- id: ai-context-guard
```
必须提交脚本并设置其可执行权限位,`script` hook 才能运行(本仓库已进行此设置):
```
git update-index --chmod=+x ai_context_guard.py
```
本仓库中还有一个现成的 [`.pre-commit-config.yaml`](.pre-commit-config.yaml),它将扫描器作为本地 hook 运行,适用于你已将 `ai_context_guard.py` 复制到自己的项目中的情况。
## 示例
[`examples/`](examples/) 文件夹中有一个 `poisoned-CLAUDE.md`(包含零宽度、双向和 tag 字符)和一个 `clean-CLAUDE.md`,因此你可以观察该工具如何抓住前者并放过后者。参见 [`examples/README.md`](examples/README.md)。
## 测试
```
python -m unittest discover -s tests -v
```
## 误报
某些被标记的字符在正确的上下文中是合法的。零宽度连接符 (U+200D) 用于 emoji 序列,而变体选择符用于塑造 emoji 的表现形式。它们几乎不应该出现在 `CLAUDE.md` 中,这也是默认情况下会标记它们的原因,但如果你确实有保留它们的正当理由,请使用 `--allow` 将其加入白名单。
## 局限性
- 它查找隐藏字符。它不判断可见文本是否具有恶意。请同时阅读你的上下文文件。
- 它扫描 UTF-8 文本。非有效 UTF-8 的文件将被报告并跳过。
- `--strip` 会移除它发现的每一个被标记的字符。请先查看报告,如果需要撤销,请依赖 `.bak` 备份。
## 贡献
欢迎提交 Issue 和 pull request。优秀的补充包括:随着新工具的出现增加更多的 agent 上下文文件名,添加更多高信号码位,以及进行打包以便 pre-commit hook 无需可执行权限位即可运行。
## 许可证
MIT。参见 [LICENSE](LICENSE)。
标签:AI安全, Chat Copilot, DNS 解析, SOC Prime, Unicode检测, 云安全监控, 开发工具, 搜索语句(dork), 逆向工具, 静态分析