news 2026/6/16 13:51:59

【智能体工具使用实战04】构建执行沙盒与安全边界

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【智能体工具使用实战04】构建执行沙盒与安全边界

第4章 构建执行沙盒与安全边界

本章你将学到

  • 为什么不能让AI生成的代码直接在你的电脑上裸跑
  • 用纯Python实现一个轻量级执行沙盒,不需要Docker
  • 沙盒的五层安全机制:临时文件、超时终止、模块白名单、输出限制、网络隔离
  • 如何测试沙盒本身是否可靠
  • 将沙盒封装为Agent可调用的execute_python工具

本章你将产出:一个经过安全测试的执行沙盒模块sandbox.py,以及一个新增了execute_python工具的Agent
全部章节:收录在专栏《AI应用工程化实战教程》之【智能体工具使用实战】


4.1 一个必须面对的问题

第3章结束时,你的Agent能读文件了。它成功读取了scores.csv,描述了数据的基本情况——有多少行、多少列、各列的名称。

但有一个问题它始终没解决:计算。

你让它分析成绩数据,它能告诉你“这份数据包含10名学生、4门课程”,但当你追问“高数的平均分是多少”时,它要么凭“感觉”估算一个数字,要么老老实实告诉你“我无法执行计算,建议你使用pandas的mean()函数”。

你在第1章就见过这个场景了。现在Agent有了read_file,但它依然缺一只真正能干活的“手”——执行代码的能力

如果Agent能调用一个execute_python工具,它就可以自己写一段pandas代码,在数据上跑一遍,拿到精确的结果。这正是我们要添加的第二个工具。

但在动手之前,有一个必须正视的问题:AI生成的代码,你敢直接在自己的电脑上跑吗?


4.2 AI生成的代码不可信

2024年,一位开发者在让AI帮他写一段数据处理脚本时,AI生成的代码里包含了一行os.remove("/")。幸亏他在执行前看了一眼。

2025年,另一个开发者让AI写一段测试脚本,AI引入了一个while True的死循环。他的电脑风扇狂转了五分钟,直到强制关机。

这不是AI“故意作恶”。而是语言模型不理解“安全”——它只是根据训练数据中的模式生成文本。它不知道os.remove("/")意味着什么,不知道死循环会让CPU占满,不知道有些库你不希望它调用。

当你的Agent学会执行代码之后,它会自己写代码、自己执行。你不是那个在编辑器里写完代码、检查一遍、再点运行的人。Agent是一个自动化的流程——它收到任务,生成代码,调用execute_python,然后拿结果。

这意味着:你必须给Agent造一个受控的执行环境,让它在里面“随便搞”,搞不出事。

这个受控的执行环境,就是沙盒。


4.3 轻量级沙盒的设计思路

提到“沙盒”,很多人首先想到Docker容器——完整的文件系统隔离、网络隔离、资源限制。Docker确实是工业级沙盒的标准方案,但它有两个问题:

第一,学习曲线陡。装Docker、理解镜像、配置容器、处理权限——这对第一次接触容器化的本科生来说,认知负荷远超本章的教学目标。我们的重点是“让Agent安全地执行代码”,不是“学会Docker”。

第二,它太重了。你只是想让Agent执行一段pandas计算,就启动一个完整的Linux容器?光是容器启动的时间可能比代码执行本身还长。

好在,对于我们的场景——执行有限功能的Python代码片段——我们完全可以用纯Python实现一个足够安全的轻量沙盒。

设计思路很简单:

安全目标实现方式
防止删除/修改你的文件代码写入临时文件,执行完自动删除
防止死循环占满CPU设置超时时间,超时强制终止
防止调用危险函数限制可用的模块,只允许pandasnumpymath等安全模块
防止输出撑爆内存限制stdout和stderr的最大长度
防止访问网络在subprocess中不提供网络访问(或通过防火墙规则)

核心实现就靠一个Python标准库模块:subprocess。它能启动一个独立的子进程,在这个子进程里执行代码。子进程有自己的内存空间,出问题不会影响主进程。你可以设置超时,超时了就杀掉子进程。你可以捕获它的输出,限制输出大小。执行完毕,子进程销毁,一切都消失。


4.4 沙盒的完整实现

4.4.1 用Trae生成沙盒代码

在Trae的AI对话面板中输入:

在项目>4.4.2 审查生成的代码

Trae生成sandbox.py后,打开它,对照以下清单逐项检查:

核心实现检查

  • 是否使用了tempfile.NamedTemporaryFile
  • 文件后缀是否为.py
  • 是否设置了delete=False(因为需要在另一个进程中读取)?
  • 执行后是否用os.unlink()手动删除了临时文件?
  • 是否使用了subprocess.run并传入了timeout
  • 返回格式是否与要求一致?

安全机制检查

  • 是否定义了白名单模块列表?
  • 是否在代码中扫描了import语句并与白名单对比?
  • 是否定义了危险关键字列表并扫描了代码?
  • stdout和stderr是否做了截断?
  • 异常情况(超时、代码中有危险操作)是否返回了清晰的错误信息?

如果发现缺失或实现不当,在Trae对话面板中要求修正。例如:

sandbox.py 中,你只检查了 "import os" 这种形式,但 "from os import system" 这种形式不会被检测到。请同时检查两种 import 形式。

或者:

sandbox.py 中,白名单模块检查后如果发现非法模块,应该返回 "success": false 和具体的错误信息,而不是抛出异常。

以下是沙盒核心逻辑的参考实现(供对照,不是让你手写):

importsubprocessimporttempfileimportos# 模块白名单ALLOWED_MODULES={'pandas','numpy','math','statistics','json','csv','collections','itertools','datetime','re','string','decimal','fractions'}# 危险关键字DANGEROUS_KEYWORDS=['os.system','subprocess','eval(','exec(','__import__','shutil','sys.','os.','pathlib','requests','urllib','socket','ftp','http']defcheck_code_safety(code:str)->tuple:"""检查代码是否安全。返回 (is_safe, error_message)"""# 检查危险关键字forkeywordinDANGEROUS_KEYWORDS:ifkeywordincode:returnFalse,f"代码包含危险操作:{keyword}"# 检查 import 语句(简单字符串扫描)import_lines=[lforlincode.split('\n')ifl.strip().startswith('import ')orl.strip().startswith('from ')]forlineinimport_lines:# 提取模块名parts=line.strip().split()ifparts[0]=='import':modules=[p.split('.')[0]forpinparts[1:]ifp!='as']else:# from X import Ymodules=[parts[1].split('.')[0]]formodinmodules:ifmodnotinALLOWED_MODULES:returnFalse,f"不允许导入模块:{mod}(白名单之外的模块)"returnTrue,None

4.5 安全机制逐层拆解

现在花一点时间,理解沙盒每一层安全机制的设计逻辑。这不仅是审查代码,更是培养设计安全系统的工程思维。

第一层:临时文件隔离

每次执行代码,都创建一个随机的临时文件(如/tmp/tmpabc123.py),把代码写进去,执行完立刻删除。这样做的好处是:即使代码里写入了某些文件,也只会影响临时文件(已经被删了),不会污染你的项目目录。每次执行都是“全新的”,上一次执行的残留不会影响下一次。

第二层:超时终止

subprocess.run(timeout=10)意味着如果代码在10秒内没有执行完,子进程会被强制杀死。这防止了死循环永远运行下去。10秒是一个合理的默认值——大多数数据分析操作(计算平均值、筛选数据)都在1秒内完成。如果你的数据特别大,可以在调用时传入更大的timeout

第三层:模块白名单

这是最核心的一层。代码在执行前会被扫描——它导入了哪些模块?如果发现不在白名单里的模块,直接拒绝执行。

白名单的设计原则是最小权限:只给Agent完成任务必需的模块,不给多余的。数据分析需要pandasnumpy,数学计算需要math,文件解析需要csvjsonossys不需要——Agent不应该有能力操作操作系统。requests不需要——Agent不应该能发起网络请求。

第四层:输出限制

如果Agent写了一段代码,生成了10万行输出,你的终端和内存都会撑爆。所以 stdout 和 stderr 各截断到5000字符——足够看到计算结果和错误信息,但不会造成资源问题。

第五层:危险关键字扫描

模块白名单能拦住import os,但如果Agent不写import而是直接调用内置的危险函数呢?危险关键字扫描就是为此设计的——它直接在代码文本中搜索os.systemsubprocessevalexec等字符串。只要出现,就拒绝执行。

当然,这种基于关键字扫描的方式不是100%安全的(比如有人可以把危险代码混淆),但对于我们的教学场景已经足够。工业级沙盒会使用更复杂的技术(如seccomp、ptrace),但那超出了本书的范围。


4.6 【避坑指南】AI生成代码的五种危险操作

当Agent开始自己写代码并自动执行时,你可能会遇到以下情况。提前了解,能帮你快速诊断问题。

危险操作表现沙盒防御层如果沙盒没有拦住
死循环while True: pass超时终止(10秒后强制杀掉)CPU风扇狂转,Agent卡住不动
文件删除os.remove("important.txt")模块白名单(os不允许)+ 临时文件隔离项目文件被删除
网络请求requests.get("恶意网址")模块白名单(requests不允许)+ 危险关键字数据泄露
系统命令os.system("rm -rf /")危险关键字扫描 + 模块白名单灾难性后果
内存炸弹[0] * 10**12或无限递归超时终止(内存耗尽前进程被杀死)系统卡死

如果Agent生成的代码被沙盒拦截了怎么办?

这本身就是一个很好的学习机会。在终端日志里,你会看到Agent调用了execute_python,但沙盒返回了{"success": false, "error": "代码包含危险操作:os.system"}。Agent拿到这个结果后,通常会尝试修改代码——去掉危险操作,换一种安全的方式。这个过程就是“Agent在沙盒的约束下学会安全编程”。

如果你想让Agent更好地理解沙盒的限制,在它的系统提示词中加入:

你可以使用 execute_python 工具来执行Python代码。但请注意: - 只允许使用以下模块:pandas, numpy, math, statistics, json, csv, collections, itertools, datetime, re, string, decimal, fractions - 不要使用 os、sys、subprocess、requests 等模块 - 代码必须在10秒内完成执行 - 如果沙盒拒绝了你的代码,请检查是否有不允许的导入或操作,修改后重试

4.7 测试沙盒本身是否可靠

沙盒是给你Agent用的安全基础设施。在把它交给Agent之前,你需要先验证它自己是否可靠。

创建test_sandbox.py

"""测试沙盒的安全性和功能"""fromsandboximportexecute_python# 测试1:正常代码print("测试1:正常计算")result=execute_python("print(sum([1,2,3,4,5]))")print(f"结果:{result}\n")# 测试2:死循环(应该被超时终止)print("测试2:死循环")result=execute_python("while True: pass",timeout=3)print(f"结果:{result}\n")# 测试3:尝试导入 os(应该被白名单拦截)print("测试3:尝试导入os")result=execute_python("import os\nprint(os.getcwd())")print(f"结果:{result}\n")# 测试4:尝试执行系统命令(应该被关键字扫描拦截)print("测试4:尝试执行系统命令")result=execute_python("import os\nos.system('ls')")print(f"结果:{result}\n")# 测试5:超长输出(应该被截断)print("测试5:超长输出")result=execute_python("for i in range(10000): print(f'Line {i}')")print(f"stdout长度:{len(result.get('stdout',''))}\n")# 测试6:pandas 操作(应该正常执行)print("测试6:pandas操作")result=execute_python(""" import pandas as pd data = {'name': ['Alice', 'Bob'], 'score': [90, 85]} df = pd.DataFrame(data) print(df.describe()) """)print(f"结果:{result}")

运行测试:

python test_sandbox.py

期望结果:

  • 测试1:返回success: true,stdout为15
  • 测试2:返回success: false,error中包含“超时”
  • 测试3:返回success: false,error中包含“不允许导入模块:os”
  • 测试4:返回success: false(要么被模块白名单拦,要么被关键字扫描拦)
  • 测试5:返回success: true,但stdout被截断到5000字符
  • 测试6:返回success: true,stdout中包含pandas的描述统计

如果所有测试都通过,你的沙盒可以交付给Agent使用了。


4.8 将沙盒封装为Agent工具

沙盒就绪,现在把它添加到Agent的工具箱里。

4.8.1 设计 execute_python 工具描述

在Agent看来,execute_python是一个可以执行Python代码的工具。它需要知道:这个工具能做什么、什么时候该用它、有什么限制。

打开agent.py,在Trae对话面板中输入:

请修改 agent.py,增加第二个工具 execute_python。 工具描述: - 名称:execute_python - 用途:在安全沙盒中执行Python代码,返回执行结果。适用于需要计算、数据处理、统计分析的任务。 - 限制:只允许使用 pandas, numpy, math, statistics, json, csv, collections, itertools, datetime, re, string, decimal, fractions 模块。代码需在10秒内完成。不支持网络访问、文件系统操作(除了沙盒内部的临时文件)。 - 参数: - code(必填,字符串):要执行的Python代码 - timeout(可选,整数,默认10):超时时间(秒) 实现: - 导入 sandbox 模块中的 execute_python 函数 - 在 TOOL_MAP 中添加 "execute_python" - 在 tools 列表中添加新工具的定义 - 在系统提示词中补充:当需要计算、统计、数据处理时,使用 execute_python 工具
4.8.2 审查新增的工具代码

确认以下几点:

  • 工具定义中的name是否与TOOL_MAP的键一致?
  • description中是否说明了限制(白名单模块、超时)?
  • 系统提示词中是否更新了execute_python的使用指引?
  • sandbox.execute_python的导入路径是否正确?

4.9 集成测试:读取数据并执行计算

现在agent.py有了两个工具:read_fileexecute_python

运行以下测试,观察Agent如何组合使用它们:

python agent.py

修改agent.py底部的测试请求为:

run_agent("请读取 scores.csv,然后计算高数的平均分。")

观察终端日志。你期望看到的流程是:

第1轮:Agent调用 read_file("scores.csv") 第2轮:Agent调用 execute_python("import pandas as pd\ndf = pd.read_csv('scores.csv')\nprint(df['高数'].mean())") 第3轮:Agent基于两次工具调用的结果,生成最终分析

如果Agent在第2轮写入的代码中尝试df = pd.read_csv('scores.csv'),这是可以的——pandas在白名单中,read_csv是pandas的正常功能。沙盒不会拦截它。

但注意:沙盒中的代码执行环境和Agent的主进程是隔离的。在沙盒里pd.read_csv('scores.csv')能读到文件,是因为scores.csv在项目根目录,而沙盒子进程的工作目录继承了主进程的目录。如果你想让沙盒更安全,可以在sandbox.py中切换工作目录到一个临时文件夹——但那样Agent就必须在代码中处理文件路径问题。当前方案在安全性和可用性之间取了一个平衡。


4.10 本章小结

  • AI生成的代码不可信——语言模型不理解安全,它生成的代码必须放在受控环境中执行。
  • 轻量级沙盒不需要Docker——用subprocess+tempfile+ 超时 + 模块白名单,纯Python即可实现足够安全的执行环境。
  • 五层安全机制:临时文件隔离、超时终止、模块白名单、输出限制、危险关键字扫描。每一层解决一类安全威胁。
  • 沙盒本身必须先测试——在交给Agent使用之前,用各种攻击场景验证沙盒的可靠性。
  • Agent现在有了两只手read_file读取数据,execute_python执行计算。组合使用,它就能完成第1章那个“分析成绩单”的任务。

下一章,我们将为Agent添加第三个工具——write_file,并构建一个完整的ToolManager类来管理工具箱。Agent将能够读取数据、执行计算、保存分析报告——一个完整的数据分析闭环。


课后练习

  1. 运行test_sandbox.py中的全部六个测试,确认沙盒正常工作。如果某个测试失败了,分析是哪一层安全机制没有生效。
  2. 修改sandbox.py,在白名单中增加matplotlib.pyplot(但matplotlib可能依赖os等模块——这会触发什么安全拦截?你如何解决这个矛盾?)
  3. 运行集成测试——让Agent读取scores.csv并计算高数平均分。如果Agent在代码中写了import os然后被沙盒拒绝,观察Agent的后续行为——它会怎么修改代码?
  4. (进阶)在sandbox.py中增加第六层安全机制:限制子进程的内存使用。提示:在Linux/macOS上可以使用resource模块,在Windows上可以研究job objects

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

5步轻松掌握网页视频下载:VideoDownloadHelper实用指南

5步轻松掌握网页视频下载:VideoDownloadHelper实用指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经遇到过这样的情…

作者头像 李华
网站建设 2026/6/16 13:43:51

大模型开源与闭源竞争格局

大模型开源与闭源竞争格局📝 本章学习目标:通过本章学习,你将全面掌握"大模型开源与闭源竞争格局"这一核心主题,建立系统性认知。一、引言:为什么这个话题如此重要 在人工智能快速发展的今天,大模…

作者头像 李华
网站建设 2026/6/16 13:42:59

哔咔漫画下载器终极指南:轻松打造个人离线漫画图书馆

哔咔漫画下载器终极指南:轻松打造个人离线漫画图书馆 【免费下载链接】picacomic-downloader 哔咔漫画 picacomic pica漫画 bika漫画 PicACG 多线程下载器,带图形界面 带收藏夹,已打包exe 下载速度飞快 项目地址: https://gitcode.com/gh_m…

作者头像 李华
网站建设 2026/6/16 13:41:56

Effective C++ 条款36:绝不重新定义继承而来的 non-virtual 函数

Effective C 条款36:绝不重新定义继承而来的 non-virtual 函数本篇为《Effective C:改善程序与设计的 55 个具体做法》读书笔记系列第 36 篇。开篇引言 在 C 的面向对象编程中,继承和多态是两个核心概念。很多开发者习惯性地认为:…

作者头像 李华
网站建设 2026/6/16 13:40:52

SiYuan笔记数据迁移终极指南:3步完成跨设备无缝转移

SiYuan笔记数据迁移终极指南:3步完成跨设备无缝转移 【免费下载链接】siyuan A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. 项目地址: https://gitcode.com/GitHub_Trending/si/…

作者头像 李华