检查 AI 生成的 Python 代码是否包含危险调用,可以先用 Bandit 扫描 Python 语法树。它会定位一些已知的风险模式,例如 eval 和拼接输入后调用 shell=True。报告提供规则、代码行、严重程度和判断置信度,便于逐条复核;扫描通过仍需结合权限、数据流和实际业务审查。
安装后先扫描教学样例,不运行危险函数
本文实际验证环境为 Windows、Python 3.13.14、Bandit 1.9.4。新建练习目录后执行:

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install bandit==1.9.4
.\.venv\Scripts\python.exe -m bandit --version
Bandit 1.9.4 要求 Python 3.10 或更新版本。macOS 或 Linux 将路径换为 .venv/bin/python。项目已配置工具时沿用项目版本;安装与递归扫描方式见Bandit 官方入门文档。
下面是故意带问题的教学代码,保存为 generated_bad.py。不要给这两个函数喂真实用户输入,也不需要运行它们:
import subprocess
def compute(text):
return eval(text)
def list_dir(user_path):
return subprocess.check_output('dir ' + user_path, shell=True)
扫描单文件,保存 JSON:
.\.venv\Scripts\python.exe -m bandit generated_bad.py -f json -o bandit-before.json
Bandit 在本例中实际返回退出码 1,JSON 的 errors 为空,results 有 3 条。扫整个项目可用 bandit -r src,但路径要指向业务源码,避免把虚拟环境和第三方库一起扫入。不要先加严重程度过滤,否则入门时可能漏看低级别提示。
| 规则 | 本例报告 | 如何判断 |
|---|---|---|
| B404 | 第 1 行导入 subprocess,LOW / HIGH | 提醒查看子进程使用,导入本身不等于已经存在可利用漏洞 |
| B307 | 第 5 行 eval,MEDIUM / HIGH | 字符串可能被作为 Python 表达式执行,必须核对输入来源 |
| B602 | 第 9 行 shell=True,HIGH / HIGH | 外部输入参与 shell 命令字符串,需检查命令注入路径 |
表中斜线前为 Severity,后为 Confidence。Confidence 高表示规则对这一代码模式的判断较确定,不是“漏洞利用概率高”。规则解释可查危险调用列表和B602 官方说明。
按真实任务替换危险调用
先把需求缩小并说清:compute 只求 JSON 数字数组之和;list_dir 只列出工作目录下 uploads 内指定目录的一层文件名。不需要任意表达式执行,也不需要 shell。保存为 generated_fixed.py:
import json
from pathlib import Path
def compute(text):
values = json.loads(text)
if not isinstance(values, list) or not values:
raise ValueError('需要非空数字数组')
if any(type(value) not in (int, float) for value in values):
raise ValueError('数组只能包含数字')
return sum(values)
def list_dir(user_path):
root = Path('uploads').resolve()
target = (root / user_path).resolve()
if not target.is_relative_to(root):
raise ValueError('目录超出 uploads')
if not target.is_dir():
raise ValueError('目录不存在')
return sorted(path.name for path in target.iterdir())
先进行路径归一化,再检查目标是否仍在根目录内,可以拒绝 .. 向上跳出目录的请求。这里没有调用子进程,避免了 shell 命令拼接。若真实任务必须调用外部程序,应核对固定可执行文件、参数列表和输入白名单;仅把 shell=True 改成 False 不能证明所有输入都可信,B603也提醒检查无 shell 子进程的输入。
复扫后,还要核对修复有没有破坏功能
.\.venv\Scripts\python.exe -m bandit generated_fixed.py -f json -o bandit-after.json
.\.venv\Scripts\python.exe -c "from generated_fixed import compute; assert compute('[1,2,3]') == 6; print('求和样例通过')"
修复稿在本文环境中实际得到退出码 0、errors=[]、results=[]。另外实际检查了数字数组求和、拒绝布尔值、拒绝空数组、拒绝对象,以及拒绝路径 .. 五个条件。读者应保留修复前后的 JSON 与代码差异,再核对自己业务里的合法输入仍能得到正确结果。
目录示例可以在练习目录创建 uploads/demo,放一个无敏感信息的文件,然后调用 list_dir('demo') 核对返回文件名;调用 list_dir('..') 应得到“目录超出 uploads”。这些是验证方法,不是本文已完成的真实服务器权限测试。
上面的修复只用于受控练习目录。真实文件服务还需做用户归属校验、限制文件名与响应数量、避免符号链接和检查后路径被替换的竞争问题,并限制请求体大小。JSON 示例也未限制超大数组、浮点非有限值和溢出,不能直接作为对外的计算 API。扫描器不会替你确认这些业务前提。
遇到误报和已有问题,怎样处理?
先读输入从哪里来、是否可能被用户控制,再判断规则是否适用。不要为得到绿灯全局跳过 B602 或批量添加 nosec。确有误报时,记录具体规则与理由,缩小例外范围,并让评审能看见。官方支持 JSON 基线对比,但基线只方便识别新增问题,不会修复历史问题。
最终检查分成三个结果:工具是否完整扫描、危险模式是否已消除、业务验证是否通过。如果 JSON 的 errors 非空或文件被跳过,先解决扫描失败;没有检出项不能替代依赖漏洞检查和授权审查。关于 AI 草稿中还有哪些风险,可继续阅读AI 编程的代码质量与安全风险。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30542.html