rwrife/canary-cage
GitHub: rwrife/canary-cage
canary-cage 在代码仓库中布设隐蔽的 prompt-injection 陷阱,用于检测和告警 AI 编程 agent 遭受 Agentjacking 攻击的行为。
Stars: 0 | Forks: 0
# 🐤 canary-cage
**状态:** v0.1 开发中。参见 [PLAN.md](./PLAN.md)。
## 安装说明
```
# 推荐:通过 pipx 进行隔离安装
pipx install canary-cage
# 或者,从 checkout 进行开发:
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
```
要求 Python 3.11+。除了 `typer`、`rich` 和 `pydantic` 之外,该包没有其他非标准库运行时依赖项 —— webhook beacon 使用的是 `urllib`,因此安装体积保持很小。
## 缘由
Agentjacking —— 即攻击者通过投毒你的 AI 编程 agent 所读取的内容(如 README、issue、deps)来诱骗其运行恶意代码 —— 现在已成为一种真实且被正式命名的攻击类别([The Hacker News, 2026年6月](https://thehackernews.com/2026/06/agentjacking-attack-tricks-ai-coding.html))。`canary-cage` 允许你主动在自己的仓库中布设陷阱(tripwire),以便在*第一时间*发现触发行为。
## 快速入门
```
canary init --preset chaotic-good # write canary.toml
canary plant # seed tripwires into the repo
canary list # see what's in the cage
# ... 让你的 agent 在 repo 上自由发挥 ...
canary check # exit 1 if anything fired
canary uproot # restore the repo cleanly
```
一个典型的会话如下所示:
```
$ canary plant
🐤 planted 7 canaries → /repo/.canary-cage/state.json
$ canary check
🚨 1 canary fire(s) detected
┏━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
┃ canary_id ┃ type ┃ source ┃ detail ┃
┡━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
│ md-9f3a… │ markdown │ working-tree │ sentinel missing │
└──────────┴───────────┴─────────────┴──────────────────┘
```
截至 **M4** 阶段,`plant`、`list`、`check` 和 `uproot` 已正式可用。`--type` 参数可接受
`markdown`、`docstring`、`todo` 或 `all`(默认值)。
`canary check` 会扫描工作区中缺失的 canary 标记,检查
`.canary-cage/fired/` 中是否存在残留的触发记录,并检索 git 历史
查找 canary 标记。每次检测到的触发(fire)都会被 **file beacon**
(`.canary-cage/fired/.json`)和 **log beacon**
(`.canary-cage/beacon.log`)记录。当检测到至少一次
触发时,该命令将以非零状态退出,从而使其能完美接入 CI。
### 配置说明 (M5)
在仓库根目录放置一个 `canary.toml` 文件,即可调整要植入的类型、需要跳过的路径,以及在符合条件集合中的植入密度:
```
canary init # writes a commented default canary.toml
canary init --preset paranoid # …or seed it with a named preset
```
```
[canary]
# preset = "minimal" # 仅 markdown,低密度
# preset = "chaotic-good" # 所有类型,约一半的合格文件
# preset = "paranoid" # 所有类型,无处不在
types = ["markdown", "docstring", "todo"]
ignore = ["docs/**", "vendor/**"]
density = 1.0 # 0.0–1.0
```
显式指定的字段始终优先于预设默认值。`.canary-cage/**` 和
`.git/**` 始终会被忽略。
### Webhook beacon (M6)
在 `canary.toml` 中添加一个 `[beacons.webhook]` 表,即可将每次触发以
JSON 格式 POST 到你指定的 endpoint —— 兼容 Slack/Discord/PagerDuty 的
桥接服务、你自己的收集器,或任何支持 HTTP 的服务。常驻运行的
`file` 和 `log` beacon 也会持续工作。
```
[beacons.webhook]
url = "https://hooks.example.com/canary-fires"
timeout = 5.0 # seconds per attempt
max_attempts = 3 # exponential backoff between attempts
backoff = 0.5 # base delay in seconds
headers = { Authorization = "Bearer s3cr3t" }
```
Payload 结构:
```
{
"canary_id": "md-9f3ac1",
"canary_type": "markdown",
"source": "working-tree",
"detail": "sentinel missing from README.md",
"path": "README.md",
"detected_at": "2026-06-20T17:40:00Z"
}
```
如果每次重试均失败,该记录将被追加到
`.canary-cage/webhook.dead` 中,确保你绝不会因为不稳定的
接收端而丢失任何触发记录。
### Slack / Discord beacon
在 canary 触发的瞬间及时通知聊天频道。Slack 和 Discord 均
提供了 incoming-webhook URL;将其中一个(或两者)放入 `canary.toml`:
```
[beacons.slack]
url = "https://hooks.slack.com/services/T000/B000/XXX"
snippet_chars = 240 # bytes of the affected file to attach (0 disables)
[beacons.discord]
url = "https://discord.com/api/webhooks/000/XXX"
```
每次触发都会被渲染为一条简短消息,其中包含 canary 的 id、类型、
来源、受影响的路径,以及可选的文件内容代码片段,这样值班人员无需
离开聊天界面即可直观查看 agent 修改了什么。其重试和死信(dead-letter)机制与原始的
webhook beacon 相同(发送失败的记录会存入 `.canary-cage/chat.dead`)。
### MCP server 模式
将 canary 状态公开为 MCP 工具,以便*受信任的* agent 能够自我证明,从而避免误触已布设的陷阱。该 server 通过
stdio 使用 JSON-RPC 2.0 进行通信 —— 只需将你的 MCP host 指向:
```
canary mcp
```
系统会公布以下三个工具:
- `canary_list` —— 列出所有已植入的 canary(id、类型、路径、标记预览),
以便 agent 知道应该忽略什么。
- `canary_status` —— 按类型统计数量、证明次数、上次检测到的
触发。
- `canary_attest` —— 记录 agent 的自我身份标识
(`{ "agent": "claude-code", "purpose": "refactor" }`)。存储于
`.canary-cage/attestations.json`。
一个被囚禁(jailed)或被劫持(jacked)且未读取 MCP 工具的 agent 将无从知晓
该避开什么 —— 这正是其核心目的所在。
### Pre-commit 防护机制
安装一个 git hook 来阻止两类意外情况:
- *未经* `canary uproot` *而移除* 已植入 canary 的提交(从而防止
agent —— 或粗心的人类 —— 悄悄地移除陷阱)。
- 将 `.canary-cage/fired/` 或
`.canary-cage/beacon.log` 下的任何内容暂存到提交中(触发的
取证证据必须保留在本地)。
```
canary install-hook # writes .git/hooks/pre-commit
canary precommit # what the hook runs; exits 1 on violations
```
使用 `--force` 可覆盖现有的 pre-commit hook。
## 开发说明
```
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
ruff check .
pytest
```
## 核心概念
- **Canary** —— 放置在仓库中的微小且隐蔽的内容(markdown 注释、零宽 docstring payload、诱饵 TODO、诱骗文件)。
- **Beacon** —— 当 canary 被触发时(如写入文件、日志记录、webhook)作出的响应动作。
- **Cage** —— 经过监控配置的你的仓库。
## 许可证
MIT —— 完整范围请参阅 [PLAN.md](./PLAN.md)。
标签:AI安全, AI编程助手, Chat Copilot, DLL 劫持, 大语言模型, 搜索语句(dork), 蜜标, 逆向工具