MukundaKatta/agentguard
GitHub: MukundaKatta/agentguard
专为 AI 智能体设计的轻量级网络出站防火墙,通过声明式域名白名单和请求预算限制拦截非授权外联,防止提示注入等攻击导致的数据泄露。
Stars: 0 | Forks: 0
# agentguard
[](https://www.npmjs.com/package/@mukundakatta/agentguard)
[](https://www.npmjs.com/package/@mukundakatta/agentguard)
[](./LICENSE)
[](https://nodejs.org)
[](./test)
**AI 智能体的网络出站防火墙。** 通过声明式域名允许列表控制智能体工具可获取的资源;对其他任何请求则抛出异常(或返回 403)。零运行时依赖。可直接嵌入任何调用 `fetch()` 的代码,包括您无法控制的 SDK 客户端。
```
npm install @mukundakatta/agentguard
```
```
import { firewall, policy, PolicyViolation } from '@mukundakatta/agentguard';
const safe = policy({
network: {
allow: ['api.openai.com', 'api.anthropic.com', '*.example.com'],
methods: ['GET', 'POST'],
},
budget: { maxRequests: 50 },
violations: 'throw',
});
await firewall(safe, async () => {
await myAgent.run('summarize today\'s news'); // any fetch outside the allowlist throws
});
```
如果工具调用(或模型驱动的 SDK 请求)试图访问不在列表中的主机,将抛出 `PolicyViolation` 并附带 `reason`、`detail`、`url` 和 `method`。您可以捕获它、记录它、给自己发送告警,或者转交给人工审批。无论您的安全模型是什么,这都为您提供了介入的空间。
TypeScript 类型随包一起提供。
### 查看实际运行效果
```
git clone https://github.com/MukundaKatta/agentguard && cd agentguard
node examples/demo-block.js
```
三种场景——正常通过、拦截提示注入驱动的数据泄露抛出异常,以及相同场景在 `block` 模式下(返回 403 而不是抛出异常)。
## 为什么需要
当您赋予 LLM 使用 `fetch` 的工具访问权限(或任何底层使用 fetch 的 SDK)时,您是在信任模型不会去调用您不希望访问的主机。在以下情况中,这种信任会被打破:
- **提示注入**诱使模型获取攻击者控制的 URL(通过 URL 参数、DNS 查询等进行数据泄露)。
- **模型升级**悄然改变了智能体决定调用的 API。
- 工具或 SDK 的**依赖更新**悄悄添加了新的端点(遥测、备用主机)。
- **CI 测试运行**因为有人忘记 mock 而意外访问了生产环境的 API。
`agentguard` 默认将智能体驱动的 HTTP 请求视为不受信任,并为您提供只需一行代码即可配置允许访问的规则。
## API
### `policy(spec) → Policy`
验证并冻结策略声明。如果规范格式错误,则抛出 `TypeError`。
```
const p = policy({
network: {
allow: ['api.openai.com'],
deny: ['*.internal.corp'],
methods: ['GET', 'POST'],
},
budget: { maxRequests: 100 },
violations: 'throw',
});
```
主机模式:
- 精确匹配主机:`'api.openai.com'`
- 通配符子域:`'*.example.com'`(匹配 `example.com` 及其任何子域)
- 全局通配符:`'*'`(在 `deny` 中用作全捕获规则非常有用)
拒绝规则优先于允许规则。
### `firewall(spec, fn) → Promise`
通过包装 `globalThis.fetch` 来强制执行策略并运行 `fn`。退出时(包括发生异常时)会自动恢复原状。并发的 `firewall()` 调用各自拥有独立的 AsyncLocalStorage 帧,互不冲突。
```
await firewall(p, async () => {
await myAgent.run('do task'); // any fetch inside is policy-checked
});
```
### `wrapFetch(spec) → fetch`
获取一个应用了策略的 fetch 函数,而无需对全局对象进行猴子补丁。当您可以将 `fetch` 直接传递给 SDK 时,请使用此方法:
```
import Anthropic from '@anthropic-ai/sdk';
import { wrapFetch, policy } from '@mukundakatta/agentguard';
const client = new Anthropic({
fetch: wrapFetch(policy({ network: { allow: ['api.anthropic.com'] } })),
});
```
每次 `wrapFetch()` 调用都会返回一个带有独立内部请求计数器的新 fetch 函数;预算限制是针对每个 fetch 实例的。
### `check(policy, url, init?) → Decision`
纯粹的决策函数。无副作用。如果您想在 fetch 以外的传输层(例如 HTTP/2 客户端)强制执行策略,或者独立测试策略,请使用此函数。
```
const decision = check(p, 'https://evil.com', { method: 'GET' });
// { action: 'deny', reason: 'not_in_allowlist', detail: 'evil.com' }
```
### `PolicyViolation`
当请求被拒绝时(默认行为),由 `firewall()` 抛出。可通过编程方式捕获:
```
try {
await firewall(p, fn);
} catch (err) {
if (err instanceof PolicyViolation) {
console.error(err.reason, err.url, err.detail);
}
}
```
稳定的 `reason` 代码:
- `not_in_allowlist` — 主机未匹配到任何 `allow` 模式
- `denylist_match` — 主机匹配到了 `deny` 模式
- `method_blocked` — HTTP 方法不在 `network.methods` 中
- `budget_exceeded` — 超过了 `budget.maxRequests` 预算限制
- `invalid_url` — 无法解析 URL
## 配置方案
### 不得访问生产环境的 CI 智能体
```
const ciPolicy = policy({
network: {
allow: ['localhost', '127.0.0.1', '*.test.invalid'],
deny: ['*'],
},
});
await firewall(ciPolicy, () => runMyAgentTests());
```
### 生产环境中限制严格的智能体:仅允许访问其已知的 LLM 提供商
```
const prodPolicy = policy({
network: { allow: ['api.anthropic.com'] },
budget: { maxRequests: 200 },
});
await firewall(prodPolicy, () => myAgent.handle(userRequest));
```
### 需要访问整个网络但不能访问内部网络的智能体
```
const webPolicy = policy({
network: {
deny: ['*.internal.corp', '169.254.169.254', 'localhost', '127.0.0.1'],
// no allow → everything else is permitted
},
});
await firewall(webPolicy, () => researchAgent.run(query));
```
(`169.254.169.254` 是 EC2/GCP/Azure 元数据服务——一个经典的 SSRF 目标。)
### `block` 模式:返回 403 而不是抛出异常
```
const blockingPolicy = policy({
network: { allow: ['api.openai.com'] },
violations: 'block',
});
await firewall(blockingPolicy, async () => {
// blocked requests now return a synthetic 403 Response with
// `x-agentguard-block: 1` headers. Useful when you want the agent to
// see the rejection and recover, rather than crashing.
});
```
## CLI
`@mukundakatta/agentguard` 附带了一个 `agentguard` 二进制文件,用于一次性 URL 检查和 CI 期间的策略验证:
```
# 在部署前验证 policy 文件
npx -p @mukundakatta/agentguard agentguard validate-policy --policy policy.json
# 根据 policy 检查单个 URL(如果被阻止则退出码为 1)
npx -p @mukundakatta/agentguard agentguard check https://api.openai.com/v1/chat \
--policy policy.json --method POST
# 从文件(或通过 `-` 从 stdin)批量检查 URL;如果任一被拒绝则退出码为 1
cat candidate-urls.txt | npx -p @mukundakatta/agentguard agentguard check-batch - \
--policy policy.json
```
标准输出上每次检查输出一个 JSON 对象(使用 `--pretty` 可进行缩进格式化)。允许/有效时退出代码为 `0`,拒绝/无效时为 `1`,使用错误时为 `2`。运行 `agentguard --help` 获取完整的子命令参考。
## 本项目不是
- **不是沙箱。** 坚决的恶意代码可以通过猴子补丁绕过 `fetch` 本身,或使用其他传输方式(`net.connect`、`dgram`、原生 HTTP/2)。如需实现硬隔离,请使用操作系统级别的网络命名空间、Linux `iptables`、k8s `NetworkPolicy` 或 Firecracker microVM(e2b 等)。
- **不是身份验证。** 它按主机进行拦截,而不是按用户。请与 API 层的适当身份验证结合使用。
- **不是面面俱到。** v0.1 仅覆盖基于 fetch 的出站流量。文件和 Shell 出站不在此范围内(这需要对 `node:fs` 和 `node:child_process` 进行猴子补丁,这种侵入性足以破坏其他库的假设)。
正确定位是:`agentguard` 是*工具使用的安全带*。它能捕获意外情况和大多数机会主义攻击。请将其与沙箱、机密管理和身份验证结合使用,以实现深度防御。
## 相关库
智能体可靠性技术栈的一部分——全部位于 `@mukundakatta/*` 作用域下,全部零依赖:
- [`@mukundakatta/agentfit`](https://www.npmjs.com/package/@mukundakatta/agentfit) — 按预算适配消息。*适配它。*
- [`@mukundakatta/agentsnap`](https://www.npmjs.com/package/@mukundakatta/agentsnap) — 工具调用轨迹的快照测试。*测试它。*
- **`@mukundakatta/agentguard`** — 网络出站防火墙。*沙箱化。*(本库)
- [`@mukundakatta/agentvet`](https://www.npmjs.com/package/@mukundakatta/agentvet) — 工具参数验证器。*审查它。*
- [`@mukundakatta/agentcast`](https://www.npmjs.com/package/@mukundakatta/agentcast) — 结构化输出强制器。*验证它。*
自然流程:**fit → guard → snap → vet → cast**。
## 状态
v0.1.2 — 安全修复版本。核心 API 稳定。包含 TypeScript 类型。通过 47/47 项测试,支持 Node 20/22/24 上的 CI。
**v0.2 计划**(基于真实世界反馈后):
- 按工具限制速率(例如 "search_web: 10/min")
- 成本跟踪集成(根据请求量估算 $/run)
- fetch 以外的可插拔传输层(OpenAI streaming,MCP stdio)
- 审计日志钩子(每次允许/拒绝 → 发送到您选择的目标)
标签:AI Agent安全, API网关安全, Fetch拦截, GNU通用公共许可证, IP 地址批量处理, Lerna, LLM工具调用安全, MITM代理, Node.js, NPM包, OSV-Scalibr, TypeScript, 出站防火墙, 域名白名单, 声明式策略, 安全插件, 提示注入防护, 暗色界面, 模型越狱防护, 策略执行, 网络安全, 网络数据泄露防护, 网络访问控制, 自定义脚本, 隐私保护, 零依赖