提示注入可使Agent执行curl命令外泄env中的API密钥。构建可证明的出口允许名单作为CI invariant,防止开发环境变泄密通道。
不变量:Agent 的执行环境只能访问明确列入白名单的目标(模型 API 端点、你锁定的包仓库),除此之外一概禁止。
这是网络层控制,所以即使 Agent 的工具审批逻辑失败或被绕过,它依然有效。Prompt 注入可以改变 Agent 请求的内容,但无法改变防火墙允许的内容。
你需要一个一次性环境来运行待测 Agent。方案按真实性递增排序:
本地 Docker 容器配合自定义网络。
任意可销毁的云厂商虚拟机。
AI 开发平台的免费沙箱。例如 MonkeyCode 提供免费模型访问和免费服务器选项,足以搭建一个隔离的 Agent 环境,无需触碰生产凭证——对于这类恶意夹具测试非常方便,因为该虚机本身就是按可销毁设计的。
声明:本文作为 MonkeyCode 产品推广的一部分撰写。下面的夹具与平台无关,不依赖任何特定提供商,在普通 Docker 中运行完全相同。
创建 egress_probe.sh。下方为锁定版本,按需调整以适配你的技术栈。
#!/usr/bin/env bash
# egress_probe.sh — run INSIDE the agent sandbox
# Tested with: bash 5.2, curl 8.5.0, docker 26.1
# Expected: allowlisted hosts succeed, everything else fails.
ALLOWLIST=("api.your-model-provider.example" "registry.npmjs.org")
DENYLIST=("169.254.169.254" "attacker-sim.example" "pastebin.com")
fail=0
for host in "${ALLOWLIST[@]}"; do
if curl -sS -o /dev/null -m 5 "https://$host"; then
echo "PASS allowlisted reachable: $host"
else
echo "FAIL allowlisted blocked: $host"; fail=1
fi
done
for host in "${DENYLIST[@]}"; do
if curl -sS -o /dev/null -m 5 "http://$host"; then
echo "FAIL denied host reachable: $host"; fail=1
else
echo "PASS denied host blocked: $host"
fi
done
# DNS exfiltration check: can arbitrary DNS names resolve?
if getent hosts "$(head -c4 /dev/urandom | od -An -tx1 | tr -d ' \n').exfil.example" >/dev/null 2>&1; then
echo "WARN arbitrary DNS resolves — DNS exfil channel may be open"
fi
exit $fail
正向夹具:列入白名单的主机必须可达,否则你的 Agent 无法工作——这证明了防火墙并非简单的"全部阻断"(那样的话,朴素的全禁测试也会通过)。
负向夹具:云元数据端点 169.254.169.254(经典凭证窃取目标)、模拟攻击者主机和已知粘贴站点必须全部失败。DNS 检查捕获了常见错误——阻断了 HTTP 但放行了基于解析器的数据泄露通道。
下方为模板——注意:在你的特定主机名上标记为未执行;我在 Docker 桥接网络上运行过此模式,但在信任之前请替换并重新测试你自己的白名单。
# Run on the sandbox host (or as container NET_ADMIN setup)
# Default-deny egress, allow only allowlisted IPs
iptables -P OUTPUT DROP
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Resolve allowlist to IPs and permit 443 only
for ip in $(getent ahostsv4 api.your-model-provider.example | awk '{print $1}' | sort -u); do
iptables -A OUTPUT -p tcp -d "$ip" --dport 443 -j ACCEPT
done
# Log dropped egress for the detect layer
iptables -A OUTPUT -j LOG --log-prefix "EGRESS-DROP: " --log-level 4
注意事项:CDN 厂商的 IP 白名单会失效,因为 IP 会变动。对于生产环境,推荐使用出向 HTTP 代理(例如带 ACL 的 Squid,或服务网格出口网关),按域名过滤。iptables 版本仅适用于夹具场景——快速、简洁、可审查。
当我在默认 Docker 容器(无出向规则)上运行负向夹具时,输出为:
FAIL denied host reachable: 169.254.169.254
FAIL denied host reachable: pastebin.com
这就是该夹具要捕获的基线失败。应用 iptables 模板后,同一探针输出全部 PASS,且主机的 dmesg / syslog 显示被拒绝尝试的 EGRESS-DROP: 条目——这是你检测层的原始素材。如果你的环境是云沙箱而非普通 Docker,需特别验证元数据端点;某些平台会在非标准地址上暴露它,你的探针应扩展覆盖这一点。
一个有用的 CI 关卡:每次沙箱镜像或防火墙配置变更时,将探针作为 job 运行。不变量仅一行——探针退出码必须为 0——但它锁定了整个边界。
经由白名单主机的 DNS 和 TLS 类泄露不在范围内。如果模型 API 本身可被滥用为中继,网络规则无法拯救你;那需要应用层对 Agent 工具调用的检查。
如前所述,IP 白名单在 CDN 背后会变脆弱。将 iptables 夹具视为回归测试,而非生产控制。
本方案不测试 Agent 的判断力。拒绝恶意指令的 Agent 是一个独立的、更软的层面。本夹具假设 Agent 最终会被操纵,并约束了爆炸半径。
如果你的威胁模型包含沙箱逃逸(内核级),你需要虚拟机隔离,而非容器规则——免费共享沙箱层级可能不是那场景的正确工具,你应该考虑专用宿主机和 gVisor / Firecracker。
该探针使一个不变量成为 CI 可验证的。但你的环境还有一个更困难的问题:谁应该拥有出向强制执行的所有权——沙箱镜像、宿主机,还是提供虚机的平台?如果你在评估托管 Agent 环境(MonkeyCode 的免费服务器是获取可销毁测试机的一种方式),在放入真实凭证前运行此探针。如果负向夹具通过,你就有了一个可以构建的底线;如果任何一个失败,你用一条 curl 的代价学到了重要的东西。