news 2026/4/23 14:15:10

别再点“允许”了:真正安全的AI Agent沙盒,应该像监狱一样狠

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再点“允许”了:真正安全的AI Agent沙盒,应该像监狱一样狠

你有没有发现一件很可怕的事:AI Agent 越聪明,你越容易变蠢。

因为它会不断问你:

  • “我要执行 npm install,可以吗?”

  • “我要跑测试,可以吗?”

  • “我要调试错误,可以吗?”

  • “我要 curl 一个地址,可以吗?”

你一开始还认真看。 到第十次,你已经不看了——手比脑子快,直接点Yes

这不是你懒。 这是人类的大脑被系统训练出来的审批疲劳(approval fatigue)

而审批疲劳,就是安全的天敌。

所以真正的解决方案不是让 AI “问得更礼貌”,而是——让它根本没必要问。

把它关进一个盒子里。 一个它想作死也作不出去的盒子。

今天我就带你搭一个:给 AI Agent 用的 Docker 安全沙盒 + 网络代理防火墙

它能做到:

  • 允许读写你的项目目录

  • 允许联网

  • 但联网只能访问你允许的域名

  • 容器系统本身只读,删不掉 /bin

  • 就算 Agent 想偷你的 .env,也发不出去

你不需要再不断弹窗批准。 你只需要相信“笼子”,而不是相信“机器人”。

一、整体架构:别给 Agent 自由,给它规则

我们要的不是一个普通容器。 我们要的是一个“可控环境”。

整个系统有两道防线:

1)文件系统监狱(Docker)

容器内部看到的是一个只读的操作系统

它能写的地方只有:

  • 你挂载进去的项目目录(比如 /workspace)

  • 临时目录 /tmp(用 tmpfs,容器死了就清空)

它想碰你电脑里的东西? 对不起,根本看不见。

  • SSH Key?看不到

  • 你别的目录里的 .env?碰不到

  • 系统配置文件?动不了

一句话:它只能在你允许的文件夹里“折腾”。

2)网络门卫(Node.js Proxy)

更狠的来了。

我们不直接给容器开“全网通”。 我们让它所有网络请求都必须经过一个代理。

这个代理做的事很简单:

  • 请求域名在白名单 → 放行

  • 不在白名单 → 直接掐断

这就像机场安检: 你可以飞,但你不能带炸弹。

二、第一部分:写一个网络“门卫”(Proxy)

Docker 自带网络控制,但它是按 IP 控的。 问题是你真正想管的是域名,比如:

  • registry.npmjs.org

  • github.com

所以我们自己写个极简 Node.js 代理。

创建 proxy.js

新建文件proxy.js

const http = require('http'); const net = require('net'); const url = require('url'); // 1. The Policy const ALLOWED_DOMAINS = [ 'registry.npmjs.org', // For installing packages 'github.com', // For cloning repos 'api.openai.com' // If the agent needs to talk to the LLM from inside ]; const PORT = 8888; const server = http.createServer((req, res) => { // Handle standard HTTP requests (less common now, but good to have) const parsed = url.parse(req.url); if (!isAllowed(parsed.hostname)) { res.writeHead(403); res.end('Blocked by Sandbox Proxy'); console.log(`[BLOCKED] HTTP request to ${parsed.hostname}`); return; } // ... (HTTP forwarding logic would go here, omitting for brevity/HTTPS focus) }); // 2. Handle HTTPS (The CONNECT method) server.on('connect', (req, clientSocket, head) => { const { port, hostname } = url.parse(`//${req.url}`, false, true); if (!isAllowed(hostname)) { console.log(`[BLOCKED] CONNECT request to ${hostname}`); clientSocket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); clientSocket.end(); return; } console.log(`[ALLOWED] ${hostname}`); // 3. The Pipe const serverSocket = net.connect(port || 443, hostname, () => { clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); serverSocket.write(head); serverSocket.pipe(clientSocket); clientSocket.pipe(serverSocket); }); serverSocket.on('error', (err) => { console.error(`[ERROR] Connection to ${hostname} failed:`, err.message); clientSocket.end(); }); }); function isAllowed(hostname) { // Simple substring match to allow subdomains (e.g., sub.github.com) return ALLOWED_DOMAINS.some(d => hostname === d || hostname.endsWith(`.${d}`)); } server.listen(PORT, () => { console.log(`🛡️ Sandbox Proxy running on port ${PORT}`); });

启动代理

终端运行:

node proxy.js

这玩意儿就是你的“网络防火墙”。

从此以后,容器里的 AI 想联网? 先过我这一关。

三、第二部分:把 Agent 关进 Docker “牢房”

现在开始搭“监狱”。

我们的目标配置是:

  • 根目录只读(--read-only)

  • /tmp 用 tmpfs 临时存储

  • 容器里用普通用户运行,别用 root

  • 强制走 HTTP_PROXY / HTTPS_PROXY

  • 只挂载当前目录,不给它全盘权限

概念 Docker 命令(先看效果)

docker run \ --rm \ --user $(id -u):$(id -g) \ --read-only \ --tmpfs /tmp \ --network host \ -v $(pwd):/workspace \ -w /workspace \ -e HTTP_PROXY=http://localhost:8888 \ -e HTTPS_PROXY=http://localhost:8888 \ node:18-slim \ npm install

看到这里你可能会皱眉:为什么用 --network host?

原因很简单: 在 Linux 上,host 模式最省事,容器可以直接访问 localhost:8888。

如果你是 macOS 或 Windows: host 网络模式不一样,你得改成 bridge,然后代理地址写:

host.docker.internal:8888

四、第三部分:写一个“沙盒执行器”(Runner)

我们要做的,是让 AI Agent 不再直接 exec()。 它只允许调用这个 runner。

你可以理解为:

AI 想执行命令? 可以。 但只能通过“狱警”执行。

创建 sandbox-runner.js

新建sandbox-runner.js

const { spawn } = require('child_process'); const os = require('os'); const commandToRun = process.argv[2] || 'echo "No command provided"'; const isMac = os.platform() === 'darwin'; // Configure network for Mac vs Linux const networkFlag = isMac ? [] : ['--network', 'host']; const proxyHost = isMac ? 'host.docker.internal' : 'localhost'; const proxyUrl = `http://${proxyHost}:8888`; const dockerArgs = [ 'run', '--rm', // Cleanup after run '--read-only', // Immutable OS '--tmpfs', '/tmp', // Writable temp space '--tmpfs', '/run', // Needed for some tools '-v', `${process.cwd()}:/workspace`, // Mount current dir ONLY '-w', '/workspace', // Set working dir '-e', `HTTP_PROXY=${proxyUrl}`, // Force traffic to proxy '-e', `HTTPS_PROXY=${proxyUrl}`, '-e', 'NPM_CONFIG_REGISTRY=http://registry.npmjs.org/', // Force non-SSL for easier proxying, or allow HTTPS registry ...networkFlag, 'node:18-slim', // Image to use '/bin/sh', '-c', commandToRun ]; console.log(`📦 Sandboxing: "${commandToRun}"`); const child = spawn('docker', dockerArgs, { stdio: 'inherit' }); child.on('close', (code) => { console.log(`\nEnd of sandbox session. Exit code: ${code}`); });

现在你的 Agent 执行任何命令,只需要调用:

node sandbox-runner.js "npm install"

就行。

五、开始测试:让它试试“越狱”

先开代理:

node proxy.js

然后新开一个终端。

1)测试禁止访问:Google

node sandbox-runner.js "curl -I https://google.com"

结果:直接失败。 代理会输出:

[BLOCKED] CONNECT request to google.com

爽不爽? 这才叫控制权。

2)测试允许访问:GitHub

node sandbox-runner.js "curl -I https://github.com"

结果成功。

你会看到:

HTTP/1.1 200 Connection Established

3)测试删除系统文件

node sandbox-runner.js "rm -rf /bin"

结果是:

rm: cannot remove '/bin': Read-only file system

容器系统是只读的,它连“自残”都做不到。

六、为什么这套东西意义巨大?

因为它改变了安全模型。

以前的安全是什么?

以前的安全靠的是:流程

AI 每执行一步,你都要看一眼。

理论上你应该认真审查。 但现实是——你迟早会累。

累了之后你就会进入一种状态:

只要不是 rm -rf /,我就点允许。 只要它说“为了修复 bug”,我就点允许。

然后有一天,它顺手把你的.env上传到了某个地址。 你连发现都来不及。

现在的安全是什么?

现在的安全靠的是:架构

你不需要一直盯着 AI。 你只需要盯着“规则”。

AI 想把.env发到 pastebin?

对不起:

  • pastebin.com 不在白名单

  • 网络请求被代理掐断

  • 它上传不了

你甚至可以不在电脑前。 它也出不了事。

这就叫:信任盒子,不信任机器人。

七、局限性

这套方案很强,但不是“绝对安全”。

它能挡住 99% 的现实事故,但不是核弹级防御。

1)Docker Socket 是绝对禁区

永远别挂载:

/var/run/docker.sock

一旦挂载进去,Agent 就能自己启动一个特权容器。 然后越狱成功。

一句话:你等于把监狱钥匙递给犯人。

2)代理规则靠环境变量,有绕开的可能

我们靠的是:

  • HTTP_PROXY

  • HTTPS_PROXY

如果 Agent 运行某些恶意二进制,完全可以无视这些变量,直接连 IP。

企业环境里通常会用防火墙阻断非代理流量。 本地开发环境里,这套方案主要防:

  • 误操作泄露

  • 供应链攻击(npm install 拉恶意包)

  • Agent “顺手”上传敏感文件

3)性能开销

每次执行命令都要起一个容器,肯定有成本。

但对于“对话式写代码”来说,这点开销可以忽略。 如果你要极限跑测试循环,那可以把容器常驻。

八、最终结论:别让 Agent 变成你最大的安全漏洞

AI Agent 越来越强。 强到你给它权限,它真的敢乱来。

你要做的不是让它更听话, 而是让它在可控的范围里“撒野”。

你应该给它一个游乐场,而不是把整个家交给它。

你只需要三样东西:

  • proxy.js:网络门卫

  • docker read-only sandbox:文件系统牢房

  • sandbox-runner.js:统一执行入口

总共加起来也就几十行代码。

但它能帮你避免某个深夜里:

你点了第 11 次“允许” 然后第二天醒来发现密钥全没了。

如果你愿意,我还可以继续帮你把这篇文章再升级成更“咪蒙风”的版本,比如:

  • 更强的情绪钩子

  • 更像朋友圈爆款的节奏

  • 更多反问句、短句、狠句

  • 开头直接抓人那种

全栈AI·探索:涵盖动效、React Hooks、Vue 技巧、LLM 应用、Python 脚本等专栏,案例驱动实战学习,点击二维码了解更多详情。

最后:

CSS终极指南

Vue 设计模式实战指南

20个前端开发者必备的响应式布局

深入React:从基础到最佳实践完整攻略

python 技巧精讲

React Hook 深入浅出

CSS技巧与案例详解

vue2与vue3技巧合集

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:21:50

AI视频修复与水印清除工具:如何用智能技术重塑内容创作自由

AI视频修复与水印清除工具:如何用智能技术重塑内容创作自由 【免费下载链接】WatermarkRemover 批量去除视频中位置固定的水印 项目地址: https://gitcode.com/gh_mirrors/wa/WatermarkRemover 视频去水印已成为内容创作领域的关键需求,AI修复技术…

作者头像 李华
网站建设 2026/4/23 11:22:11

Local Moondream2生产环境:日均处理2000+图片的私有视觉分析平台

Local Moondream2生产环境:日均处理2000图片的私有视觉分析平台 你有没有想过,给你的电脑装上一双“眼睛”,让它能看懂图片里的一切?不是那种简单的识别物体,而是能详细描述场景、回答你的问题,甚至帮你生…

作者头像 李华
网站建设 2026/4/23 11:22:16

如何在浏览器中轻松制作专业电子书

如何在浏览器中轻松制作专业电子书 【免费下载链接】EPubBuilder 一款在线的epub格式书籍编辑器 项目地址: https://gitcode.com/gh_mirrors/ep/EPubBuilder 你是否曾想过把自己的文字变成一本精美的电子书,却被复杂的格式要求吓退?或者尝试过各种…

作者头像 李华
网站建设 2026/4/23 11:22:34

Python环境下Qwen3-TTS-12Hz-1.7B-CustomVoice的安装与快速入门

Python环境下Qwen3-TTS-12Hz-1.7B-CustomVoice的安装与快速入门 想不想用几行代码,就让电脑开口说话?而且声音还能选,从温柔的女生到沉稳的大叔,甚至还能带点情绪?今天咱们就来聊聊怎么在Python环境里,快速…

作者头像 李华
网站建设 2026/4/23 11:39:04

MiniCPM-V-2_6生物医药:实验记录本手写体OCR+关键数据提取

MiniCPM-V-2_6生物医药:实验记录本手写体OCR关键数据提取 1. 引言 在生物医药研究领域,实验记录本是科研工作的核心载体。传统的手写记录方式虽然灵活,但面临数据难以数字化、检索困难等问题。MiniCPM-V-2_6作为新一代多模态大模型&#xf…

作者头像 李华