内容
# Agent Wormhole
[](https://github.com/runningoffcode/agent-wormhole/actions/workflows/ci.yml)
[](https://pypi.org/project/wormhole-guard/)
[](https://www.npmjs.com/package/wormhole-x402)
[](https://pypi.org/project/wormhole-guard/)
[](LICENSE)
[](pyproject.toml)
[](#no-telemetry)
[](corpus/)
**您的代理互相通信。确保它们不会传递任何内容。**
**[agentwormhole.com](https://agentwormhole.com)** · [wormhole-guard on PyPI](https://pypi.org/project/wormhole-guard/) · [wormhole-x402 on npm](https://www.npmjs.com/package/wormhole-x402)
代理生成代理,移交工作,评论问题,并读取彼此的输出。一个被泄露的代理停止成为受害者并成为传播者——而另一侧的助手与您的助手一样 obedient。
在其下面,是一个不对称的 nobody 拥有:您的供应商保护其自己的 `settings.json`,但没有任何东西保护您的 `CLAUDE.md`、`AGENTS.md` 或 `.cursor/rules`,默认情况下,您的代理可以写入所有这些文件。
```
$ wormhole scan .
CRITICAL SessionStart hook executes a script from an unusual path [AUTOSTART-002]
.claude/settings.json
`node .github/setup.js` runs unprompted on SessionStart. This survives
uninstalling the package that planted it.
HIGH Agent config not in baseline [BASELINE-003]
.cursor/rules/setup.mdc
This file was not present when the baseline was taken.
```
除了 Python 3.8+ 之外,没有任何依赖。无需帐户,无需 API 令牌,无需网络调用。您的 `CLAUDE.md` 永远不会离开机器。
## 为什么
**2026 年 6 月:Miasma 蠕虫禁用了 73 个 Microsoft GitHub 仓库。** 它没有利用内存漏洞。它写入了代理配置:
| 文件 | 机制 |
|---|---|
| `.claude/settings.json` | `SessionStart` hook → `node .github/setup.js` |
| `.gemini/settings.json` | same |
| `.cursor/rules/setup.mdc` | `alwaysApply: true`, "run the setup script" |
| `.vscode/tasks.json` | `runOn: folderOpen` |
| `package.json` | hijacked `test` script |
它针对 15 个 AI 编码代理,持久性 **在 `npm uninstall` 后幸存下来**,在重新安装代理后仍然存在——设置文件比它们本身更持久。它还对每次写入进行重新加密,因此匹配已知有效载荷的哈希值永远不会找到它。
五个锚点中有四个不需要模型参与。钩子在会话启动时触发。这就是为什么此工具检查配置,而不仅仅是检查文本。
另外两个因素使差距结构化而不是偶然:
- **Cursor 被告知并拒绝拥有它。** Pillar Security 的 Rules File Backdoor(于 2025 年 2 月至 3 月披露)将指令隐藏在 `.cursor/rules` 中,使用不可见的 Unicode。Cursor 的回应是风险归于用户负责。这是您承担该责任的方式。
- **沙盒隔离不涵盖重要文件。** Claude Code 自己的文档指出,*“Read, Edit, and Write 直接使用权限系统,而不是通过沙盒运行”*,默认情况下对工作目录具有写入权限。下面研究的结果——沙盒隔离将攻击成功率降至零——并不适用于默认安装。
机制论文是 [arXiv:2603.15727](https://arxiv.org/abs/2603.15727)(预印本,2026 年 3 月,修订版 2026 年 7 月):2250 次试验,82% 通过技能供应链中毒实现攻击成功(3 个向量中 63% 的综合成功率),启用沙盒隔离后为 0% - 以及 **82 个公开索引的代理配置中没有一个启用它**。62% 的网关身份验证代替,它不能阻止传播。
有效的防御存在,但没有人使用它。这个差距是一个工具问题,这个工具就是解决方案。参见 [MISSION.md](MISSION.md)。
### 有效载荷如何传播
一条消息进入,两个代理被感染,第一个步骤之后没有攻击者——红色箭头是您自己的代理执行它们的工作:
<img src="assets/diagram/propagation-2x.png" alt="Sequence diagram: an attacker sends text carrying a payload to your agent, which stores it in memory, retrieves it as context, and hands it to a peer agent, which stores it in turn. The red steps require no attacker." width="820">
`harden` 停止存储,`readguard` 检查从模型返回的内容,`outbound` 拒绝移交。
## 安装
```bash
pipx install wormhole-guard
wormhole scan ~/your-project --blast-radius
```
发行版为 `wormhole-guard`。PyPI 上的 `agent-wormhole` 是一个无关项目。命令和导入包均为 `wormhole`。
仅限标准库,因此它也可以直接从 checkout 运行,无需安装步骤:
```bash
git clone https://github.com/runningoffcode/agent-wormhole
cd agent-wormhole
python3 -m wormhole scan ~/your-project --blast-radius
```
## 使用
预防 - 这些在有效载荷落地之前运行:
```bash
wormhole init ~/project # harden + baseline + print the hooks
wormhole outbound --install # sends: refuse to pass a payload on
wormhole readguard --install # reads: PostToolUse + InstructionsLoaded
wormhole guard --install # writes: the PreToolUse hook
wormhole harden ~/project --apply # drop the write bit, block creation
wormhole harden ~/project --undo --apply # restore write permission
```
三个门。`readguard` 涵盖到达的内容 - 获取的页面、shell 输出、MCP 响应 - 这是 2026 年所有公开披露的代理泄露方式。`outbound` 涵盖您的代理传递给子代理、对等代理或另一个团队的 bot 将读取的问题。`guard` 和 `harden` 涵盖是否可以持久化到下一个会话。
`outbound` 是唯一默认阻止的。入站内容根据定义是不可信的,并且有很多内容,因此这些规则保持保守。出站由您的代理自己编写,因此有效载荷出现在那里已经异常 - 而被拒绝的发送会大声失败,而离开的发送会到达操作员,从未同意信任您。
检测和隔离 - 这些在之后运行:
```bash
wormhole scan ~/project --blast-radius # payloads, posture, blast radius
wormhole baseline ~/project # fingerprint configs
wormhole verify ~/project # detect modification
wormhole watch --limit 20 # injection attempts in tool output
wormhole capture ~/project # preview capture (dry run)
wormhole capture ~/project --apply # capture, preserving originals
wormhole captured # list what has been contained
wormhole restore <id> # pull one back out, byte-for-byte
wormhole insights # what the capture history reveals
wormhole handoffs # payloads in agent-to-agent tasks
wormhole corpus ./docs # documents before they are embedded
```
`handoffs` 和 `corpus` 涵盖了该工具最不擅长的两个向量,并且值得说明。传递给子代理的任务描述没有拦截点 - 父代理在内存中编写它 - 因此 `handoffs` 事后读取记录。矢量存储没有标准格式,因此 `corpus` 在 **嵌入之前** 扫描文档,这是文本仍然是文本的最后一个点。
`guard` 默认发出警告。阻止模式仅拒绝 WORM-001 和 WORM-003 - 两个具有明确结构签名且没有语料库误报的规则 - 因为阻止工具中的规则缺陷会停止合法工作而不是打印噪声。
`scan` 和 `watch` 在 `--fail-on` 处或以上退出(默认为 `high`),因此它们直接进入 CI。
## 虫洞
捕获的有效载荷进入虫洞而不是 bin。
```bash
wormhole capture ~/project --apply # excise payloads, keep originals
wormhole captured # what has been captured
wormhole restore <id> # pull one back out (false positive)
wormhole export ./samples # inert fixtures for rule development
```
删除有效载荷会破坏证明感染所需证据:编写了什么,何时编写,是否传播。它还会将误报变成数据丢失,这是安全工具失去用户的方式。因此,原始文件以完整的 provenance 记录以字节为单位保存,每个捕获都是可逆的。
迭代运行摘除 - 摘除,重新扫描,重复 - 因为有效载荷可以占据多个独立块。AgentWorm 的双锚点设计使用恰好两个,删除第一个将留下第二个活动,同时使文件看起来被处理。如果文件无法清理,运行会显示 `INCOMPLETE` 而不是声称成功。
虫洞是 `0700`;有效载荷存储为 `0400`,后缀为 `.quarantined`,因此其中的内容都不会作为代理配置加载或执行。
## 它精确地做了什么
这是 **您的代理读取的指令文件的完整性监视器**。重要的部分不关心有效载荷的内容。
| | | 是否能经受改写? |
|---|---|---|
| **预防** | `harden` 移除写入,并预创建缺失的配置路径,因此有效载荷无法创建新的路径 | 是 - 无需规则 |
| **通知** | `baseline`/`verify` 对每个配置进行哈希;更改或未记录的文件是发现结果 | 是 - 哈希对文字内容无所谓 |
| **拒绝** | `guard` 检查待写入的内容并可以拒绝 | 部分 - 基于规则 |
| **检测** | 有效载荷形状的内容规则,自动启动配置规则,能力姿势规则 | 否 - 可规避,用于分类 |
| **隔离** | `capture` 摘除有效载荷,保存原始字节以便恢复 | 不适用 |
顺序是刻意的。预防和完整性是持久的半部分;规则是基于便利性的附加功能。一个工具如果以其规则数量为竞争轴心,那么它将在一个衰减的轴心上竞争。
驱动感染率为零的控制是沙盒隔离,它存在于您的代理框架中,而不是此处 - Anthropic 自己的文档指出,它默认不涵盖 Read/Edit/Write。
## 检测规则
**内容** - 类似于自我复制的有效载荷的文本:
| | |
|---|---|
| `WORM-001` | 自我复制指令(自引用 + 复制动词 + 目标) |
| `WORM-002` | 指令覆盖短语 |
| `WORM-003` | 将凭证泄露到外部目的地 |
| `WORM-004` | HTML 注释中隐藏的指令 |
| `WORM-005` | 零宽度字符 |
| `WORM-006` | Unicode 标签块走私(不可见,模型可读) |
| `WORM-007` | 隐瞒指令(“不要告诉用户”) |
**自动启动** - 无需提示和模型即可执行的配置。这是实际传播的形状:
| | |
|---|---|
| `AUTOSTART-001` | 无人值守的钩子下载并执行(`curl … \| sh`) |
| `AUTOSTART-002` | 无人值守的钩子从配置目录运行脚本 |
| `AUTOSTART-003` | 无人值守的钩子运行解释器 |
| `AUTOSTART-004` | Cursor 规则始终应用,指示代理运行命令 |
`PreToolUse` 被刻意视为无人值守 - 它因为代理已经在行动,并且这是 `guard` 本身如何发货。
**MCP 工具完整性** - 这里唯一一个从未接触磁盘的工件。服务器在连接时回答 `tools/list`,返回的名称,描述和模式被注入模型的上下文中,在那里它们作为指令读取。协议中没有任何内容会签名该答案,也没有任何内容要求客户端重新检查它,因此服务器可以是您审查时良性的,而一周后可能不同意,没有文件更改。
| | |
|---|---|
| `MCP-001` | 工具定义不再与记录的内容匹配 |
| `MCP-002` | 在基线中未记录的工具 |
| `MCP-003` | 记录的工具不再被声明 |
| `MCP-WORM-*` | 内容规则应用于工具描述 |
`wormhole baseline` 除了配置文件外,还对它们进行指纹识别;`verify` 报告漂移。重新格式化的 JSON 不是更改 - 只有名称,描述和哈希被哈希。
**姿势** - 有效载荷可以实现的内容:无限制 shell(`POSTURE-001`),网络出口(`-002`),缺少拒绝规则(`-003`),可写配置(`-004`),远程 MCP 服务器(`-005`),已安装技能(`-006`)。
**完整性** - `BASELINE-001/002/003`:更改,丢失或未跟踪的配置。这是捕获无法预料的有效载荷的部分。
**运行时** - `RUNTIME-*`:应用于会话记录中工具输出的内容规则,涵盖从未接触磁盘的供应链通道。
## 回归套件
```
$ ./loop/replay.sh
detected 15/15 clean 14/14 FN=0 FP=0
```
**这是回归套件,而不是检测率。** 它在为此存储库编写的 fixtures 上进行测量,因此它证明规则在更改后仍然表现如预期 - 而不是更多。任何引用它作为对抗真实攻击者的准确性的内容,包括我们,都是夸大其词。基于规则的检测本质上是可规避的:Trail of Bits 绕过了每个主要的技能扫描器,耗时不到一个小时,而改写单独击败已发布的分类器。
套件强制执行使规则可用的纪律:每个恶意 fixtures 都附带一个**良性双胞胎**,它保留有效载荷的 incriminating 表面特征,仅更改规则键控的属性。关键字匹配器在两个方向上都失败。如果规则在双胞胎上触发,则不会发货。这捕获了两个实际的假阴性和一个关键的假阳性发布前。
额外验证了 7 个真实项目:0 个发现。
## 两个软件包
| | 保护 | 安装 |
|---|---|---|
| **[wormhole-guard](https://pypi.org/project/wormhole-guard/)** | 您的编码代理读取的指令文件 | `pipx install wormhole-guard` |
| **[wormhole-x402](https://www.npmjs.com/package/wormhole-x402)** | 您的代理签署的付款 | `npm install wormhole-x402` |
相同的论文,两个代理读取指令的地方不同。Python 核心依赖项免费;TypeScript 软件包没有任何网络调用。两者都不调用任何地方。
## 当代理持有钱包时
上述所有内容都会使您恢复。更改一个变量,它就不再可恢复:一个读取它不控制的文件的代理,并且还可以签署交易。
`wormhole-x402` 是应用于付款的相同想法。每个交易安全产品都会回答 **此交易将执行什么** - 模拟,资产差异,地址声誉。 None of it helps here,因为付款到攻击者的地址模拟完美。正确的余额,无需恢复,干净的判决。交易有效;它只是不是要求的交易。
```bash
npm install wormhole-x402
```
```ts
import { guardSigner } from "wormhole-x402";
const wallet = guardSigner(myWallet, () => currentQuote);
// 签名抛出,除非交易与服务器的 402 响应匹配。
```
约束使它起作用:**意图永远不是代理声明的内容**。如果它是一个字段模型填写,妥协的模型将填写双方并验证自己的伪造。在 x402 中,收款人,金额和铸币作为结构化 JSON 在 HTTP 402 响应到达之前到达,模型的上下文之外。比较然后是纯粹的离线算术 - ~1ms,无 RPC。
<img src="assets/diagram/x402-guard-2x.png" alt="Diagram: x402 报价通过模型永远不会触摸的通道到达,商家的代币账户由纯数学派生;未签名的交易在模型的上下文中编写;单个比较允许报价付款并拒绝错误的目标,错误的金额或添加的委托人." width="820>
完整的详细信息,包括它故意不做的所有内容,在 [x402-guard/](x402-guard/)。
## 无保修
Apache 2.0,责任条款值得阅读而不是假设:
> 除适用法律要求或书面同意外,许可方提供 **“AS IS”,不提供任何保证或条件**,无论是 http://www.apache.org/licenses/by-sa/4.0/deed.en.html
> Unless required by applicable law or agreed to in writing, Licensor provides the Work **"AS IS", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND**, either express or implied. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
>
> In no event shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work.
— [LICENSE](LICENSE), §7 and §8
In plain terms: this is a detection and hardening tool, not a guarantee. It can miss a payload it has never seen, it can be wrong about one it has, and it does not make an agent safe. Read [Limits](#limits) before you rely on it for anything, and keep the control that actually works — sandbox isolation — on your list regardless.
Apache 2.0 also carries an express patent grant (§3), which is why this project stays on it rather than moving to a shorter permissive license.
## 无遥测
该工具读取您设置中最敏感的表面:提示、权限、凭证相关的配置,以及您的代理视为指令的文件内容。因此,它不会将任何这些数据发送到任何地方。
- 无需账户,无需 API 令牌,任何时候都不会进行网络调用。
- 除了 Python 标准库之外,没有其他依赖,因此不会引入任何可能在以后更改此内容的依赖。
- 基线和捕获存储在您的机器上的 `~/.wormhole` 中。
- `wormhole insights` 在本地分析您自己的捕获历史。故意没有全局信息流 - 构建一个全局信息流需要的数据正是本承诺禁止的数据。
将固定装置贡献到上游是一个单独的、故意的行为(`wormhole export`),而导出是无效的:无实时端点,无有效载荷。
验证它,而不是相信它。整个工具大约有 4,000 行无依赖的 Python 代码:
```bash
# 在任何地方都没有导入网络客户端。这将打印出 nothing。
grep -rnE "^\s*(import|from)\s+(socket|urllib|http|requests|aiohttp)" wormhole/
```
## 支持的配置格式
`AGENTS.md`、`CLAUDE.md`、`GEMINI.md`、`.cursorrules`、`.cursor/rules/*.mdc`、`.windsurfrules`、`.windsurf/rules/*.md`、`.github/copilot-instructions.md`、`.github/instructions/*.instructions.md`。
权限分析目前最了解 Claude Code 的 `settings.json`。
## 持续审计
```bash
loop/install-cron.sh # 每 6 小时;--remove 卸载
```
当没有更改时保持沉默;记录到 `~/.wormhole/logs/` 并在跟踪的配置被修改或出现有效载荷时引发通知。
[loop/RESEARCH.md](loop/RESEARCH.md) 记录了如何在不降低误报率的情况下添加新规则。
## CI
```yaml
- uses: runningoffcode/agent-wormhole@v1
with:
fail-on: high
```
## MCP 服务器
允许代理审计自己的姿态。设计上只读 - 它报告但从不写入,因为一个安全工具可以要求修改配置本身就是一个注入目标。
```json
{
"mcpServers": {
"wormhole": {
"command": "python3",
"args": ["-m", "wormhole.mcp_server"],
"cwd": "/path/to/agent-wormhole"
}
}
}
```
工具:`scan_agent_configs`、`check_integrity`、`blast_radius`、`scan_session_history`。
## 限制
明确说明,因为一个过度声称的安全工具比没有安全工具更糟糕:
- 正则表达式规则捕获*形状*,而不是含义。新颖的措辞可以避免它们 - 这就是为什么 `baseline`/`verify` 存在并且比规则覆盖率更重要。
- `watch` 读取事后的记录。它告诉您注入尝试已经到达您的代理;它不会阻止它。
- 这里没有任何内容可以从正在运行的代理中删除感染。`wormhole` 清洁文件。
- Miasma 在野外得到确认,它通过软件包安装传播,同时通过代理配置持续存在。**完全自主**的自我复制 - 有效载荷在没有涉及软件包管理器的情况下重写自身到对等方的配置中 - 仍在实验室中演示,而不是观察到。我们不会模糊这两个。
## 贡献
每个新的检测规则都附带一个良性双胞胎 - 一个讨论相同攻击但不是攻击的文件。如果规则在此双胞胎上触发,则不会发布。参见 [CONTRIBUTING.md](CONTRIBUTING.md) 和 [SECURITY.md](SECURITY.md)。
## 许可证
Apache 2.0。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器