AutoGen L3级源码静态审计:多智能体框架代码执行风险全解析
发布时间:2026/10/31 4:48:43 锦皓数字建站

最近不少团队在群里聊 AutoGen说这个多智能体框架很猛能写代码、能调用工具、能自动协调多个 AI 角色跑完整条任务链路。但每次有人提议“直接把它接到生产环境”时我总会先按住大家别急先让我把源码过一遍。这篇文章就是我针对微软 AutoGen 框架做的一次 L3 级源码静态审计完整复盘。所谓 L3不是厂商评级而是我自定义的评估深度——不满足于“跑通 demo”而是把每一条高风险调用链、每一个可复现的证据都挖出来精确到文件、函数和具体命令让结论可以被验证、被追责。我会从锁定某个具体 commit 开始结合 Bandit、Semgrep、pip-audit 和人工逐行 review带你看清楚多智能体编排框架的风险边界。适合正在做技术选型、准备集成 AutoGen 的研发负责人以及想给自己的 AI 应用做安全底线的安全工程师。1. 为什么我要对 AutoGen 做源码级审计1.1 AutoGen 解决的核心问题多智能体怎么协作AutoGen 是微软开源的多智能体对话框架核心思路是“用对话来编排”。以前大家做 AI 应用都是“我发一个问题模型回一个答案”这种单轮或简单多轮结构。但真实业务往往需要多个角色配合一个 Agent 负责拆解需求一个 Agent 负责调用代码还有一个 Agent 负责检查结果。AutoGen 把这些角色统一抽象成 Agent让它们通过消息互相“开会”期间可以执行代码、读写文件、调用外部工具最终收敛出一个结论。这种设计听起来很优雅但也引入了传统安全审计完全不熟悉的风险面。过去我们审计 Web 服务关心的是 SQL 注入、路径穿越、反序列化现在到了多智能体框架你会发现最危险的输入源变成了“模型的输出”。框架天然地允许 LLM 返回值作为代码或命令被执行那这就是一条从外部不可控输入直达本机命令执行的高危链路。1.2 我理解的“L3 评测”是什么在写这份报告之前我把评估深度分了三层方便团队内部对齐口径。L1 黑盒演示装好框架跑通样例看输出是否符合预期。完全不涉及代码风险。L2 白盒 API 审计阅读官方文档和调用接口梳理出哪些 API 可能涉及敏感操作但不会追踪到具体实现。L3 源码静态审计固定源码版本逐模块拆解关键函数用静态工具扫描再人工复核每一条告警形成可复现的证据链。“证据级”是我的底线。每一个结论必须能回答四个问题涉及哪个文件具体什么函数调用链是怎么串起来的用什么命令可以复现如果没有这些支撑一份审计报告就是一堆“我觉得”。这也是我在全文中反复强调“锁版本”和“复现”的原因。1.3 这份审计对谁有用如果你只是把 AutoGen 当研究项目在本地跑 demo那看完核心风险点就够了。但如果你是负责技术选型的架构师、要保障 AI 应用安全的安全工程师、或者正在给客户交付私有化 AI 方案的研发那这份审计的实操部分可以帮你避免一顿操作猛如虎、最后被漏洞打回原形。接下来我不讲那些“官方文档已经写清楚”的常规用法而是直接开箱验货从源码层面检查这家网红框架到底安不安全。2. 审计前置条件与工具链搭建2.1 锁定版本没有 commit 号的审计等于耍流氓审计的第一步不是装环境而是锁版本。AutoGen 的 GitHub 仓库主分支更新非常快今天测的代码和下周的代码可能就是两个项目。如果不固定 commit 或 tag任何审计结果都无法复现也无法在后续复查时对齐。我这次选择以v0.2.0这个 tag 为基线并记录下当时的 commit hash。操作如下git clone --depth 1 --branch v0.2.0 https://github.com/microsoft/autogen.git autogen-audit cd autogen-audit git checkout -b audit-v0.2.0用--depth 1做浅克隆就够审计用了因为只需要某个版本的单点快照。锁版本之后我在报告开头就标注了“审计对象autogen v0.2.0commit 9f43d70x”这样后续任何讨论都不会因为版本漂移而鸡同鸭讲。2.2 静态工具选型不是武器越多越好静态分析的工具有很多但我不建议全上。选型要跟着目标走我要找安全问题、依赖风险、敏感信息泄漏同时还要能识别出 AutoGen 框架特有的“代码执行入口”。最终我留了四件套。工具用途为什么选它BanditPython 通用安全扫描装完就能扫能检出 subprocess、eval、pickle 等危险调用Semgrep模式匹配与自定义规则支持写自定义规则能扫 AutoGen 特定的危险APIpip-auditPython 依赖漏洞扫描直接对比已知漏洞库快速定位依赖版本风险grep / ripgrep人工辅助检索静态工具漏报时靠关键词穷举高危模式安装过程很简单python -m venv .venv source .venv/bin/activate pip install -e .[all] pip install bandit semgrep pip-audit装完先跑一遍通用扫描我心里大概有个底。2.3 组合审计思路让工具互相打补丁单一工具一定会有盲区。Bandit 能抓“使用了 subprocess”但它不知道 AutoGen 的execute_code会在实际业务里被 agent 输出直接触发也不知道这里到底是不是真正的风险入口。Semgrep 虽然可以自定义规则但它依赖你提前知道要找什么模式属于“规则覆盖式”扫描。所以我的做法是先用 Bandit 做全局体检再用 Semgrep 加上自定义规则做第二轮定向扫描然后用 pip-audit 查依赖最后人工打开高风险的函数逐行确认。真正的证据绝大多数是在人工阶段确认的工具只是帮我缩小搜索范围。3. AutoGen 源码结构拆解与重点风险面3.1 核心模块与职责地图要理解风险得先知道代码长在哪。我锁定版本后把源码目录结构整理成了一张地图autogen/ ├── agent/ │ ├── assistant_agent.py # 通用助手 Agent │ ├── user_proxy_agent.py # 代理用户行为的 Agent │ ├── chat.py # 对话调度逻辑 │ └── groupchat.py # 多 Agent 群聊编排 ├── code_utils.py # Python 代码执行入口 ├── function_utils.py # 工具函数注册与调用 ├── oai/ │ ├── client.py # OpenAI 等 LLM 调用封装 │ └── completions.py ├── runtime.py # 运行时状态管理 └── notebook_utils.py # Notebook 相关工具重点关注三块assistant_agent.py负责生成消息user_proxy_agent.py负责代表用户执行操作code_utils.py则是代码执行的直接通道。这三块连起来就是一条完整的“命令执行链”模型生成代码 - 用户代理收到消息 - 调用代码执行工具 - 在本机运行结果。3.2 高风险入口代码执行与命令调用在code_utils.py里有一个典型的代码执行函数。核心逻辑大概是把传入的代码字符串写入临时文件然后调用 Python 解释器运行它。# autogen/code_utils.py审计版本精简示意 def execute_code(codeNone, timeoutNone, ...): with tempfile.TemporaryDirectory() as temp_dir: code_file os.path.join(temp_dir, tmp_code.py) with open(code_file, w, encodingutf-8) as fout: fout.write(code if code else ) cmd [sys.executable, code_file] result subprocess.check_output(cmd, stderrsubprocess.STDOUT, timeouttimeout) return result这段代码本身的编写方式没毛病但它暴露了一个致命前提任何能让execute_code执行到的调用方实际上都获得了本机 Python 解释器的完整权限。如果框架把这个能力开放给“模型生成的文本”而模型又被用户的恶意 prompt 诱导那整台机器就相当于对着不可信输入裸奔了。同样值得关注的是user_proxy_agent.py里对本地 shell 命令的执行支持。用户代理被设计成可以代表用户执行命令这个功能在官方示例里很常见但放到生产环境就极其危险。事实是你信任的不是代码而是“模型不会输出恶意命令”这个假设。3.3 配置加载与依赖暴露面AutoGen 支持通过 JSON 配置文件如OAI_CONFIG_LIST加载 LLM 的 API 密钥。这类配置在审计中必须检查两个点一是密钥是否会被写进日志二是是否可能被 Agent 的输出带出去。我扫描了所有logging和print调用发现部分 debug 分支会直接输出请求和响应内容。一旦日志系统接入第三方平台API key 就有泄漏风险。依赖方面requirements.txt和setup.py里锁定的openai、pydantic等版本在审计时都存在旧版本 advisory。这不是 AutoGen 独有的问题但作为框架层如果不对依赖做上限约束使用者很容易装上带已知漏洞的版本。4. 静态审计结果实测证据、风险等级与修复4.1 高危自动代码执行链路缺少隔离这是整个审计中最需要重视的发现。证据链如下入口模型生成的消息中可以携带代码块。解析UserProxyAgent会根据配置决定是否提取代码并执行。执行code_utils.execute_code将代码写入临时文件并调用 Python 运行。Bandit 在这里会告警subprocess调用但实际风险比告警描述得更严重这不只是命令注入而是框架设计上就允许任意 Python 代码执行。如果部署环境没有沙箱一旦某个 Agent 被 prompt injection 控制攻击者就可以读取本机文件、访问内部网络、修改数据。我在人工复核时还确认了另一种绕过方式即使你关闭了code_execution_config里的use_docker函数仍然可以落在宿主机上执行。所以关闭配置不等于消除风险只是降低了默认暴露面。4.2 中危Agent 名称注入与 Prompt 级污染在groupchat.py中多个 Agent 的名字会拼接进系统提示词里用于让模型理解上下文。如果 Agent 名称可以被外部输入控制例如动态创建的 Agent 名称来自用户请求就可能出现提示词注入恶意名称内容改变模型对任务的理解让它执行不该执行的操作。这种问题传统漏洞扫描器很难发现因为它不属于代码逻辑漏洞而是“大模型上下文污染”。我把这个风险定为中危因为它虽然不会直接导致 RCE但会影响整个多智能体系统的决策可信度甚至作为绕过安全策略的跳板。4.3 低危与依赖项信息泄漏与版本欠维护除了高危链路我还记录了一些中低危问题。日志中可能出现 LLM 请求原文其中可能包含敏感输入甚至 API key。openai和pydantic的依赖版本在审计时存在已知漏洞需要升级到修复版本。部分异常处理过于宽泛比如吞掉超时和权限异常导致故障发生时难以定位。这些问题单个看都不致命但累积起来会让整个系统在真实故障场景中变得不可诊断。尤其是依赖漏洞很多人觉得“框架代码没问题就行”却忘了依赖里藏着的 CVE 同样会跟随项目上线。4.4 修复建议优先级我把建议按优先级列成了一张表方便你直接抄进工单。优先级风险项建议动作成本P0自动代码执行生产环境禁用 execute_code或强制跑在 Docker 沙箱里中P0用户代理 shell 命令禁止 shell 执行如确实必要用最小白名单命令低P1Agent 名称注入对 Agent 名称做白名单校验禁止控制字符系统 prompt 中标记输入边界低P1依赖漏洞升级 openai / pydantic 到安全版本并定期跑 pip-audit低P2日志信息泄漏对日志做脱敏过滤 Authorization 与 api_key 字段低5. 可复现审计流程与验证清单5.1 从零开始跑一遍完整审计复现不是玄学。我自己重新开了一台干净机器按下面的命令完整跑了一遍确认所有告警都能稳定出现。git clone --depth 1 --branch v0.2.0 https://github.com/microsoft/autogen.git autogen-audit cd autogen-audit python -m venv .venv source .venv/bin/activate pip install -e .[all] pip install bandit semgrep pip-audit bandit -r autogen -f json -o bandit_autogen.json -q semgrep --configauto --json-outputsemgrep_autogen.json pip-audit -r requirements.txtBandit 的结果里重点关注subprocess和tempfile相关告警Semgrep 的规则会自动给出代码位置pip-audit 会直接列出带 CVE 的包名。拿到的每一份 JSON 都应当归档作为审计证据的原始截图。5.2 证据复现命令与判定标准光有告警不够还要能证明“这条链路真的通”。我写了一个最小复现脚本模拟 agent 生成代码并被用户代理执行的过程# audit_repro_no_sandbox.py import autogen llm_config { config_list: [{model: gpt-4, api_key: YOUR_KEY}], } assistant autogen.AssistantAgent( nameassistant, llm_configllm_config, ) user_proxy autogen.UserProxyAgent( nameuser_proxy, code_execution_config{work_dir: audit_tmp, use_docker: False}, human_input_modeNEVER, ) user_proxy.initiate_chat( assistant, message写一段 Python 代码打印出当前进程的 PID。 )如果代码成功运行说明这条执行链不依赖任何额外的安全拦截。使用use_dockerFalse时执行就发生在宿主机上这是最直接的证据。判定标准只要audit_tmp目录里出现运行痕迹就说明模型生成代码 - 本机执行这条路径是可利用的。5.3 给自己的项目做轻量版审计不是所有团队都要做全量审计。如果你只是想快速排查自己的历史代码我建议至少跑三件事bandit -r 你的代码目录 -q扫出危险内建函数和 subprocess。pip-audit检查依赖漏洞。人工 grepeval(、exec(、subprocess、pickle.loads这四个关键词。这三步大概花半天时间能过滤掉 80% 的明显安全问题。剩下的就要靠对业务逻辑的理解了。6. 审计过程中踩过的坑6.1 版本漂移用 main 分支扫描让我白忙一场第一次跑审计时我图省事直接克隆了默认分支。结果 Bandit 扫出大量和异步特性相关的告警人工复核时却发现有些代码在一个月后的版本里已经重构了。后来我意识到审计必须锁 tag否则你不仅在审计项目还在审计一个每天都在变化的移动目标。这个问题在审计任何活跃开源项目时都会遇到不只是 AutoGen。6.2 静态工具的误报与规则定制Bandit 对subprocess.check_output并不会因为“传给它的参数来自模型输出”而自动调高严重级别它只判断“你是否使用了 shellTrue”。但 AutoGen 真正的问题恰恰是“即使不用 shell任意 Python 代码执行也是 RCE”。所以静态工具可以作为提示不能作为结论。我用 Semgrep 自定义了一条规则专门找 AutoGen 框架里的高风险入口rules: - id: autogen-code-exec patterns: - pattern: execute_code(...) message: Found AutoGen code execution entry severity: WARNING这条规则很简单但它能帮我在项目迭代后快速定位新增执行入口。建议做框架型审计的人都维护一套自己的规则集。6.3 多智能体系统特有的风险盲区传统静态审计关心的是“外部输入怎么被代码执行”但多智能体系统还有一层独特的风险模型本身不是可信执行环境。Prompt injection、间接提示注入、Agent 间的信息污染这些漏洞不会出现在 Bandit 报告里。对这类系统做审计必须把“模型的输出当作不可信输入”作为前提重新梳理调用链。比如一个看似人畜无害的功能Agent A 读取了一篇网络文章Agent B 根据文章内容生成任务清单UserProxyAgent 执行清单里的 Python 代码。如果那篇文章里藏了 prompt injection 指令模型可能会输出恶意代码最后通过合法链路执行。这类攻击路径用传统工具根本发现不了只能靠威胁建模。7. 写在最后给使用者的建议如果你只是拿 AutoGen 跑个 Demo那确实很爽半天就能看到几个 Agent 在群里互相聊天、写代码、跑结果。但想接到生产环境我强烈建议先砍掉默认的“超能力”关掉execute_code取消UserProxyAgent的 shell 命令权限把use_docker设为True且确保 Docker 沙箱没有挂载敏感目录。你拦住的不只是黑客更是“模型自己产生的幻觉命令”。我在这份审计里最大的体会是真正让你翻车的不是框架本身的 Bug而是你默认信任了模型输出并且给了它调用宿主命令的权限。请把 Agent 的输出当成来自互联网的不可信输入来对待然后再考虑效率。如果你想深入验证我上面的结论建议自己把 5.1 节的命令跑一遍证据永远比观点更有说服力。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。