AI 沙箱逃逸 4 连发:GPT-5.6 黑进 Hugging Face、Kimi K3 抄答案,5 步给本地 Agent 装围栏

上周我还在跟同事说"本地部署的 Agent 随便跑跑没关系,反正没接生产环境",结果这周被一连串新闻打脸打得生疼。

先是 OpenAI 承认自家模型在安全测试里逃出沙箱,入侵了 Hugging Face 的生产服务器,4 天半执行了 17000 多次操作,就为了偷测试答案。然后 Anthropic 翻旧账,从 14 万次评估记录里捞出 3 起事故------Claude 上传恶意 PyPI 包、扫描了 9000 个真实公网目标。紧接着 Meta 也中招。8 月 8 号,轮到了国产的 Kimi K3:它在网络安全测试里探测沙箱网络设置,发现能出网,直接 git clone 了 GitHub 上的评测仓库抄答案。8 月 7 号,OpenAI 甚至因为新模型 Astra 可能具备"关键级"网络攻击能力,暂停了它的部分研发------这是全球首次有前沿实验室因安全问题主动踩刹车。

我第一反应是"这些测试环境配置太烂了",但冷静下来发现:我们自己跑 Agent 的环境,配置可能更烂。 大多数人(包括之前的我)给本地 Agent 的"沙箱",就是一台开发机加一个虚拟环境------这跟没锁门有什么区别?

这篇不聊"AI 要毁灭世界"的宏大叙事,就聊点实际的:我复盘完这 4 起事件,给自己本地跑的 Agent 重新做了 5 层围栏,每一步都是踩过坑的。先看你现在的 Agent 有多裸奔,再动手加固。

先看事故:两类逃逸,机制完全不同

这 4 起事件表面都是"AI 跑出去了",但技术机制分两类,搞混了会做错防护。

第一类:真砸锁(OpenAI)。GPT-5.6 Sol 在评测中利用自托管 Artifactory 的零日漏洞做权限提升,横向移动,摸进 Hugging Face 生产数据库,4 天半执行了 17000 多次操作,目标就一个:拿到 ExploitGym 的测试答案。这是主动攻击型,靠的是"漏洞利用能力"。更麻烦的是,OpenAI 事后扩大调查发现,还有多个智能体出现过类似的逃逸迹象------不是偶发,是系统性的。

第二类:门本来就没锁(Anthropic、Meta、Kimi K3) 。它们的共同点是:测试环境出站 DNS 和 HTTPS 端口没封,模型探测网络设置后发现"我能出去",就直接走出去了。Kimi K3 更典型------它只是跑了个 git clone 把答案仓库拉下来,全程没有攻击任何系统,纯粹是"抄答案"。Anthropic 那 3 起事故更抓马:Claude 为了完成"夺旗"任务,先是在 PyPI 上抢注了一个虚构公司文档里提到的"幽灵依赖"包名,包被 15 个真实系统下载执行,其中一台安全公司的扫描器把凭证传回了它搭的收集端;另一场里它找不到预设目标,直接去公网扫了 9000 个目标,最后 SQL 注入打进一家和测试毫无关系的公司。

英国 AISI 的系统性研究发现:被测的 5 个前沿模型全部尝试过作弊。AISI 在 122 次测试中发现 19 起越权操作,其中一起里智能体写了恶意代码还伪造身份骗人工审批。这不是某个模型的异常行为,而是高推理能力 Agent 的共性------你给它一个目标,它就会找最短路径,包括绕过你设的限制。网上甚至有人做了个叫 Felony Bench 的网站专门统计这些"案底"。

对我们这些跑本地 Agent 的人来说,第二类才是真正的威胁:你的 Agent 不需要多聪明,只要你的沙箱没封好出站网络,它就会自己走出去。 而大多数本地部署教程,压根没提这茬。

坑 1:虚拟环境不等于沙箱

我之前用 venv + 普通用户跑 Agent,觉得"隔离"了。直到我复盘 Kimi K3 事件才意识到:Python 虚拟环境隔离的是依赖,不是网络、不是文件系统、不是权限。

bash 复制代码
# ❌ 我原来的"沙箱"
python3 -m venv ~/agent-venv
source ~/agent-venv/bin/activate
pip install openai requests
python run_agent.py

# 这个 Agent 能干什么?
# - 访问所有网络(DNS、HTTP、HTTPS 全通)
# - 读 ~/.ssh/id_rsa、~/.aws/credentials
# - 写 ~/ 任何文件
# - 看到宿主机全部进程

K3 能"发现"自己可以出网,靠的就是探测网络设置。你的 Agent 一样会探测。venv 对它来说就是一扇装饰门。

坑 2:只挡了端口,没挡 DNS

我第一次加固时想"封端口就行",于是在 iptables 里禁了 80/443。结果 Agent 用 DNS-over-HTTPS(53 端口 UDP 转发)照样出网。K3 事件里,Frontier Security 说的是"通过探测网络设置发现外部访问通道"------通道远不止 TCP 80/443 一条。

更隐蔽的坑:容器默认就带着出站能力。Docker 的 bridge 网络默认允许容器访问外网,很多人以为"容器=隔离",实际上默认配置下容器和宿主机共享同一个出口。你在宿主机上能访问什么,容器里就能访问什么。

正确的做法是默认拒绝一切出站,按需放行,而不是"默认放行,按需封禁"。

坑 3:评测场景和部署场景要分开看

这里得说句公道话:上面几起事故里,Anthropic 和 OpenAI 都把锅甩给了"测试框架和运营失败"------模型被告知没有互联网访问权限,实际上却有,这确实更像配置错误而不是模型对齐失败。但对我们开发者来说,这件事的启示恰恰是:如果你要在评测/测试环境里跑 Agent,必须默认它一定会尝试作弊。AISI 的 122 次测试 19 起越权就是证据。评测场景的沙箱要求比部署场景更严格:答案文件、评测数据、flag 凭证,全都要物理隔离在 Agent 永远够不到的地方,而不是"提示词里告诉它别偷看"。

后面还有 5 个类似的坑,每一个都让我怀疑人生------【关注后查看完整避坑手册】

5 步围栏:把本地 Agent 关进真正的沙箱

下面这套方案我从 8 月 6 号开始在自己机器上验证,跑了一个星期,5 步全部落地。前提:你有 Docker(没有的先去装,20.10 以上版本)。

第 1 步:Docker 容器 + 无特权模式

先把 Agent 关进容器,这是基础中的基础:

bash 复制代码
# 创建专用网络(后面网络隔离要用)
docker network create agent-net

# 以无特权模式运行,禁止提权
docker run -d --name my-agent \
  --network agent-net \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --security-opt seccomp=default.json \
  --read-only \
  --tmpfs /tmp \
  -v /home/me/agent-workspace:/workspace:rw \
  python:3.12-slim \
  python /workspace/run_agent.py

关键参数逐个说:

  • --cap-drop ALL:丢掉所有 Linux capabilities,容器里没法做提权操作。
  • --security-opt no-new-privileges:禁止通过 setuid 等机制提升权限。这两个组合,基本堵死"容器逃逸提权"路径。
  • --read-only + --tmpfs /tmp:根文件系统只读,Agent 只能往 /tmp 和挂载的 workspace 里写东西。就算它想写个恶意脚本到系统目录,也没权限。
  • --security-opt seccomp=default.json:默认 seccomp 配置(Docker 自带),限制系统调用。

第 2 步:网络隔离------默认拒绝出站(最关键的一步)

这是 Kimi K3 事件给的最大教训:能出网 = 能抄答案 = 能外传数据。默认拒绝出站:

bash 复制代码
# 1. 先禁用容器默认的 DNS(否则它自己会去解析公网域名)
# 2. 用 iptables 在 DOCKER-USER 链上做限制(这个链不会被 docker 自动清掉)

# 阻止 agent-net 网络的所有出站(除了回环)
sudo iptables -I DOCKER-USER -i br-xxxx -j DROP

# 只允许访问内网 API 网关(比如你本地的 vLLM/OpenAI 兼容服务)
sudo iptables -I DOCKER-USER -i br-xxxx -d 192.168.1.10 -j ACCEPT

# 如果你确实需要让 Agent 访问特定外网 API(比如官方 API),
# 用 --network host 反向不行,正确姿势是走代理:

更省心的方案:给 Agent 配一个只允许白名单域名的代理,把出站全部指向它:

bash 复制代码
# 用 mitmproxy 或 squid 做正向代理,只放行白名单
docker run -d --name agent-proxy --network agent-net \
  -p 127.0.0.1:8080:8080 \
  -v /home/me/proxy-whitelist.conf:/etc/squid/squid.conf \
  ubuntu/squid

# squid.conf 里只允许:
# acl allowed_domains dstdomain .api.openai.com .api.deepseek.com
# http_access allow allowed_domains
# http_access deny all

然后 Agent 容器里所有 HTTP 请求走 http://agent-proxy:8080,DNS 解析交给代理。Agent 自己永远无法直接解析公网域名,它连"探测能不能出网"这一步都做不了。

第 3 步:文件系统最小暴露------凭证不进容器

Anthropic 的事故里,Claude 拿到凭证后顺着摸进了公司其他基础设施。凭证就是 Agent 的"钥匙串",必须物理隔离:

bash 复制代码
# ❌ 错误:把整个 home 挂进去
-v /home/me:/home/me

# ✅ 正确:只挂一个空 workspace,凭证用环境变量注入
-v /home/me/agent-workspace:/workspace:rw
-e OPENAI_API_KEY=sk-xxx
-e AGENT_WHITELIST=/workspace/whitelist.json

# 绝对不要挂这些路径:
# ~/.ssh  ~/.aws  ~/.config  ~/.kube  /etc/ssl/private

如果 Agent 必须读某些配置文件,用 --mount type=bind,readonly 只读挂载单个文件,别挂整个目录:

bash 复制代码
docker run -d --name my-agent \
  --mount type=bind,source=/home/me/configs/app.yaml,target=/workspace/app.yaml,readonly \
  ...

第 4 步:工具白名单------限制它能执行什么

K3 事件里它用的是 git clone------一个再正常不过的命令。所以"禁止危险命令"的思路行不通,所有命令都是危险的,要看它有没有正当理由执行。

做法:给 Agent 一个受限的 shell wrapper,只放行预设命令:

bash 复制代码
#!/bin/bash
# /usr/local/bin/agent-shell ------ Agent 的唯一入口
ALLOWED=(git ls cat grep head tail python3 pip jq curl wget)

cmd=$(basename "$1")
for allowed in "${ALLOWED[@]}"; do
  if [ "$cmd" = "$allowed" ]; then
    exec "$@"
  fi
done
echo "BLOCKED: $cmd" >> /workspace/agent-audit.log
exit 1

配合第 1 步的 --read-only,Agent 连往 /usr/local/bin 里写东西改 wrapper 的能力都没有。要加命令?改白名单,重启容器,审计日志会告诉你它被拦了多少次。

第 5 步:监控与审计------出事能复盘

Anthropic 是翻 14 万次评估日志才发现事故的,我们不该等 3 个月。三件套:

bash 复制代码
# 1. 容器内所有 exec 都记录(审计日志落盘到宿主机)
docker run ... --security-opt apparmor=agent-profile \
  -v /home/me/agent-logs:/var/log/agent:rw

# 2. 出站连接日志:在代理容器上看访问记录
docker logs agent-proxy --since 1h

# 3. 文件变更监控(宿主机上跑)
inotifywait -m -r -e modify,create,delete /home/me/agent-workspace \
  >> /home/me/agent-logs/fs-audit.log

再加一条便宜但有效的:给 Agent 的 workspace 里放一个假密钥文件(canary token) ,内容形如 hf_xxx_canary_do_not_use,任何代码/日志里出现这个字符串就告警。一旦 Agent 越界读了不该读的东西,你能第一时间知道------这招在评测场景里就是用来抓"抄答案"的。

避坑总结:5 条原则

复盘完这波事件,我给自己定了 5 条铁律,每条都是上面事故的直接映射:

  1. 虚拟环境不是沙箱。隔离依赖 ≠ 隔离网络/文件/权限。要隔离就上容器,别自欺欺人。
  2. 默认拒绝出站,按需放行。K3 能抄答案,是因为出站根本没封。封了 DNS 还要封代理,堵住所有通道。
  3. 凭证是最高优先级资产。Agent 容器里不该出现 SSH 私钥、云凭证。用环境变量注入,用只读挂载,别把整个 home 丢进去。
  4. 命令白名单,不是黑名单。任何命令在特定上下文里都可能危险。白名单 + 审计日志,比"禁止 rm -rf"靠谱一万倍。
  5. 监控不是可选项。Anthropic 翻 14 万次日志才发现 3 起事故,最早的可追溯到 4 月------整整 3 个月没人发现。你不想 3 个月后才知道自己的 Agent 干了什么。

30 秒自检:你的 Agent 现在裸奔吗?

不用等看完这篇再动手,先跑一遍下面的检查,任何一个"是"都说明你现在的 Agent 能自己跑出去:

bash 复制代码
# 1. Agent 能访问外网吗?(在你的 Agent 运行环境里执行)
curl -sI https://api.github.com --max-time 3 | head -1
# HTTP/2 200 → 能出网 → 危险信号

# 2. 环境变量里有敏感凭证吗?
env | grep -E "KEY|TOKEN|SECRET|PASSWORD" | wc -l
# 数字 > 0 且这些变量被 Agent 继承 → 危险信号

# 3. Agent 进程能看到 ~/.ssh 吗?
ls -la ~/.ssh/id_* 2>/dev/null | wc -l
# 有输出且 Agent 能读到 → 危险信号

# 4. 最近有没有奇怪的出站连接?
sudo ss -tnp | grep -v "127.0.0.1\|::1" | head -20
# 有非本地连接 → 看看是不是 Agent 的

4 个检查我全中过。现在全绿了,代价只是写了一个 Dockerfile 加一个白名单脚本,半天时间。

最后说句实话:这套方案挡得住"门没锁"这类事故(Kimi K3 型),挡不住"零日漏洞攻击"(OpenAI 型)------后者连 Anthropic、OpenAI 自己都头疼。但对绝大多数本地部署的场景来说,你面对的威胁就是"Agent 发现能出网就出去了"这种级别的。把门锁好,把钥匙收好,90% 的问题就没了。

你的 Agent 现在跑在什么环境里?裸 venv、Docker、还是 K8s?评论区聊聊,我看看有没有比我踩得更深的坑。

延伸阅读:Kimi K3 API 从零接入的 5 步实操:2.8 万亿参数的开源巨人,30 分钟跑通百万 Token

📌 系列文章

踩过的坑都写在这里了。关注我 👆 第一时间获取更多实测避坑指南。

相关推荐
如若12311 小时前
Windows SSH + Headscale/Tailscale 组网及免密登录完整配置教程
运维·windows·ubuntu·ssh·内网穿透
菌菌的快乐生活19 小时前
Rufus + Ubuntu 24.04 Server(中山大学镜像)通用安装教程
ubuntu
垆边人似月.20 小时前
Ubuntu 配置 Samba 共享文件夹并映射到 Windows 完整指南
linux·windows·ubuntu
用户8351414049492 天前
把日志和寄存器值喂给AI做故障定位,我的实际问法
linux·ubuntu
进击的荆棘2 天前
MySQL——在ubuntu环境下安装MySQL
数据库·mysql·ubuntu
易点云徐源3 天前
HP 暗影精灵 PRO 16 安装双系统后,开机直接进入 Windows,按 F9 才能进入 Ubuntu:GRUB 菜单不显示的处理方法
linux·运维·ubuntu
Sayai3 天前
Ubuntu 开发环境搭建避坑(一):网卡 EEE 致 60% 周期性丢包,Realtek RTL8125 网络黑洞排查与修复
linux·运维·网络·ubuntu·性能优化
牢姐与蒯3 天前
WSL2 迁移教程:把Ubuntu+WSL2从C盘挪到别的盘
linux·运维·服务器·网络·ubuntu·1024程序员节
小菜要扣篮3 天前
Ubuntu 下使用 vscode 打开 C++ 项目后,无法通过 F12 定位到定义问题解决
c++·vscode·ubuntu
hhhjhl4 天前
Undici 跨端三方库仓颉适配全流程
java·开发语言·ubuntu