Bandit是专用于Python源代码静态安全扫描的工具,基于AST分析检测硬编码密钥、eval、pickle、弱哈希等漏洞模式,不检查运行环境、系统配置或依赖CVE;默认仅扫描.py文件,需注意路径指定、环境一致性、规则精简及CI中必须加--exit-code。

Bandit 不检测“运行环境”本身的安全漏洞,它只扫描 Python 源代码中的安全模式——比如硬编码密钥、不安全的 eval、pickle.loads、弱哈希调用等。如果你在查服务器配置、Python 解释器版本漏洞、操作系统权限或依赖包 CVE,Bandit 做不了这事。
bandit -r 扫不出结果?先确认它真在扫你的代码
常见现象是执行 bandit -r . 后输出 No issues identified.,但你知道项目里明明有 os.system(user_input) 这类高危代码。问题往往出在路径和文件识别上:
- Bandit 默认只处理扩展名为
.py的文件,不会扫描.pyi、.j2(Jinja 模板)、.pyd或编译后的.so - 如果源码放在
src/下,而你在项目根目录跑-r .,它会扫venv/、tests/、docs/—— 但这些目录可能被--exclude忽略了,反而漏掉src/里的真实业务代码 - 某些 IDE 自动生成的
.py文件(如 PyCharm 的__init__.pystub)内容为空或只有注释,Bandit 会跳过解析,不报错也不告警
实操建议:先用 find . -name "*.py" | head -10 确认目标文件存在;再明确指定路径,例如 bandit -r src/ app/,避免依赖默认递归范围。
为什么 bandit 报 “ModuleNotFoundError: No module named 'bandit'”?
这不是 Bandit 没装,而是 Python 解释器环境错位。尤其在使用 poetry、pipenv 或多版本 Python(pyenv)时,pip install bandit 可能装到了系统 Python 或另一个虚拟环境里,而你当前 shell 调用的是另一个解释器。
- 运行
which python(macOS/Linux)或where python(Windows),看输出路径 - 用该路径对应的解释器安装:
/path/to/your/python -m pip install bandit - 验证安装是否生效:
/path/to/your/python -c "import bandit; print(bandit.__version__)" - 若用
poetry,必须先进入 shell:poetry shell,再执行pip install bandit
直接用 pip 而非 python -m pip 是多数环境错乱的根源。
如何让 bandit 只关注真正危险的代码模式?
默认启用全部 50+ 条规则(bandit -l 可列),但多数项目只需盯住几类高价值风险:命令注入、反序列化、硬编码凭证、不安全哈希。盲目全开只会淹没信号。
- 常用高危规则 ID:
B101(assert)、B102(exec)、B112(eval)、B301/B311(pickle/yaml.load)、B404(subprocess)、B601(paramiko)、B602(subprocess.Popenwith shell=True)、B607(os.system) - 禁用低价值规则比启用高价值规则更可靠:用
--skip显式排除,例如--skip B101,B302(assert 和 marshal) - 把规则集固化到
bandit.yaml,避免每次敲长命令;注意 YAML 中skips和tests字段互斥,不能同时存在 - 对测试代码、mock 数据、生成代码(如
proto编译产物),用--exclude tests/,proto/,build/直接跳过,别靠#nosec注释污染生产逻辑
规则越少,报告越可信;信任的前提是知道每条规则在查什么、为什么关掉它。
CI 流程中 bandit 必须加 --exit-code
在 GitHub Actions、GitLab CI 等环境中,仅运行 bandit -r . 是不够的。默认情况下,即使发现严重问题,Bandit 仍以退出码 0 结束,CI 任务不会失败——等于白扫。
- 加
--exit-code:遇到任何问题(哪怕只是中危)就返回非零退出码,触发 CI 失败 - 更精细控制可用
--severity-threshold high或--confidence-threshold high,只对高置信/高严重的问题中断流程 - 输出格式选
json或sarif,方便后续解析并聚合进统一安全看板 - 务必配合
--exclude排除构建产物目录,否则 CI 容器可能因内存耗尽而超时
没加 --exit-code 的 Bandit,在 CI 里就是个安静的摆设——它看见了问题,但从不说话。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











