python-bandit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePython Bandit Security Scanning
Python Bandit 安全扫描
Bandit is a static analysis tool that finds common security issues in Python code. It processes each file, builds an AST, and runs security-focused plugins against AST nodes. Results are categorized by severity (LOW, MEDIUM, HIGH) and confidence (LOW, MEDIUM, HIGH).
Bandit 是一款用于检测Python代码中常见安全问题的静态分析工具。它会处理每个文件,构建AST(抽象语法树),并针对AST节点运行专注于安全的插件。检测结果会按照严重程度(LOW、MEDIUM、HIGH)和置信度(LOW、MEDIUM、HIGH)进行分类。
Installation
安装
Install the base package or add extras for specific features:
bash
undefined安装基础包或添加扩展以获取特定功能:
bash
undefinedBase installation
Base installation
pip install bandit
pip install bandit
With TOML config support (pyproject.toml)
With TOML config support (pyproject.toml)
pip install "bandit[toml]"
pip install "bandit[toml]"
With SARIF output (for GitHub Advanced Security)
With SARIF output (for GitHub Advanced Security)
pip install "bandit[sarif]"
pip install "bandit[sarif]"
With baseline support
With baseline support
pip install "bandit[baseline]"
Use the same Python version as the project under scan. Bandit relies on Python's `ast` module, which can only parse code valid for that interpreter version.pip install "bandit[baseline]"
请使用与待扫描项目相同的Python版本。Bandit依赖Python的`ast`模块,该模块只能解析对应解释器版本支持的有效代码。Core Usage
核心用法
Scan a full project tree:
bash
bandit -r path/to/project/Scan with severity filter (report only HIGH):
bash
bandit -r . --severity-level high扫描整个项目目录:
bash
bandit -r path/to/project/按严重程度过滤扫描结果(仅报告HIGH级别):
bash
bandit -r . --severity-level highor shorthand: -lll (high), -ll (medium+), -l (low+)
or shorthand: -lll (high), -ll (medium+), -l (low+)
bandit -r . -lll
**Scan with confidence filter:**
```bash
bandit -r . --confidence-level highbandit -r . -lll
**按置信度过滤扫描结果:**
```bash
bandit -r . --confidence-level highshorthand: -iii (high), -ii (medium+), -i (low+)
shorthand: -iii (high), -ii (medium+), -i (low+)
**Target specific test IDs only:**
```bash
bandit -r . -t B105,B106,B107 # hardcoded password checks onlySkip specific test IDs:
bash
bandit -r . -s B101 # skip assert_used (common in tests)Use a named profile:
bash
bandit examples/*.py -p ShellInjectionScan from stdin:
bash
cat myfile.py | bandit -Show N lines of context per finding:
bash
bandit -r . -n 3
**仅针对特定测试ID进行扫描:**
```bash
bandit -r . -t B105,B106,B107 # hardcoded password checks only跳过特定测试ID:
bash
bandit -r . -s B101 # skip assert_used (common in tests)使用指定配置文件:
bash
bandit examples/*.py -p ShellInjection从标准输入读取代码进行扫描:
bash
cat myfile.py | bandit -显示每个检测结果的N行上下文:
bash
bandit -r . -n 3Configuration
配置
pyproject.toml (Recommended)
pyproject.toml(推荐)
Centralize Bandit settings alongside other tooling:
toml
[tool.bandit]
exclude_dirs = ["tests", "migrations", "venv"]
skips = ["B101"] # assert_used — acceptable in test suites
tests = [] # empty = run all (minus skips)Run with explicit config pointer:
bash
bandit -c pyproject.toml -r .将Bandit的配置与其他工具的配置集中管理:
toml
[tool.bandit]
exclude_dirs = ["tests", "migrations", "venv"]
skips = ["B101"] # assert_used — acceptable in test suites
tests = [] # empty = run all (minus skips)指定配置文件路径运行扫描:
bash
bandit -c pyproject.toml -r ..bandit (INI — auto-discovered with -r)
.bandit(INI格式 - 使用-r参数时会自动识别)
ini
[bandit]
exclude = tests,migrations
skips = B101,B601
tests = B201,B301Bandit auto-discovers when invoked with . No flag needed.
.bandit-r-cini
[bandit]
exclude = tests,migrations
skips = B101,B601
tests = B201,B301当使用参数运行Bandit时,会自动识别文件,无需添加参数。
-r.bandit-cYAML Config
YAML配置
yaml
exclude_dirs: ['tests', 'path/to/file']
tests: ['B201', 'B301']
skips: ['B101', 'B601']yaml
exclude_dirs: ['tests', 'path/to/file']
tests: ['B201', 'B301']
skips: ['B101', 'B601']Override plugin-specific defaults
Override plugin-specific defaults
try_except_pass:
check_typed_exception: true
Run: `bandit -c bandit.yaml -r .`try_except_pass:
check_typed_exception: true
运行命令:`bandit -c bandit.yaml -r .`Generate a Config Template
生成配置模板
bash
bandit-config-generator > bandit.yamlbash
bandit-config-generator > bandit.yamlThen edit — remove sections you don't need, adjust defaults
Then edit — remove sections you don't need, adjust defaults
undefinedundefinedSuppressing False Positives
抑制误报
Mark individual lines with to suppress all findings:
# nosecpython
self.process = subprocess.Popen('/bin/echo', shell=True) # nosecSuppress specific test IDs only (preferred — avoids hiding future issues):
python
self.process = subprocess.Popen('/bin/ls *', shell=True) # nosec B602, B607Use the full test name as an alternative to the ID:
python
assert yaml.load("{}") == [] # nosec assert_usedAlways add a comment explaining why the suppression is justified.
在单独代码行添加标记以抑制所有检测结果:
# nosecpython
self.process = subprocess.Popen('/bin/echo', shell=True) # nosec仅抑制特定测试ID的结果(推荐方式 - 避免隐藏未来出现的问题):
python
self.process = subprocess.Popen('/bin/ls *', shell=True) # nosec B602, B607也可以使用完整的测试名称替代测试ID:
python
assert yaml.load("{}") == [] # nosec assert_used请务必添加注释说明抑制结果的合理原因。
Output Formats
输出格式
bash
bandit -r . -f json -o report.json # JSON (required for baseline)
bandit -r . -f sarif -o report.sarif # SARIF (GitHub Advanced Security)
bandit -r . -f csv -o report.csv # CSV
bandit -r . -f xml -o report.xml # XML
bandit -r . -f html -o report.html # HTML
bandit -r . -f screen # Terminal (default)
bandit -r . -f yaml -o report.yaml # YAMLbash
bandit -r . -f json -o report.json # JSON (required for baseline)
bandit -r . -f sarif -o report.sarif # SARIF (GitHub Advanced Security)
bandit -r . -f csv -o report.csv # CSV
bandit -r . -f xml -o report.xml # XML
bandit -r . -f html -o report.html # HTML
bandit -r . -f screen # Terminal (default)
bandit -r . -f yaml -o report.yaml # YAMLBaseline Workflow
基线工作流
Use baselines to track only new issues, ignoring pre-existing findings:
bash
undefined使用基线功能仅跟踪新出现的问题,忽略已存在的检测结果:
bash
undefined1. Generate a baseline from the current state of the codebase
1. 根据当前代码库状态生成基线
bandit -r . -f json -o .bandit-baseline.json
bandit -r . -f json -o .bandit-baseline.json
2. Commit the baseline to version control
2. 将基线文件提交至版本控制系统
git add .bandit-baseline.json
git add .bandit-baseline.json
3. Future scans compare against the baseline
3. 后续扫描将与基线进行对比
bandit -r . -b .bandit-baseline.json
Useful when adopting Bandit on an existing codebase — block only newly introduced issues.bandit -r . -b .bandit-baseline.json
此功能在现有代码库中引入Bandit时非常有用 — 仅阻止新引入的问题。Critical Plugin Categories
关键插件类别
Bandit test IDs follow a group scheme:
| Range | Category |
|---|---|
| B1xx | Miscellaneous |
| B2xx | App/framework misconfiguration |
| B3xx | Blacklisted calls |
| B4xx | Blacklisted imports |
| B5xx | Cryptography |
| B6xx | Injection |
| B7xx | XSS |
Bandit的测试ID遵循分组规则:
| 范围 | 类别 |
|---|---|
| B1xx | 其他杂项 |
| B2xx | 应用/框架配置错误 |
| B3xx | 黑名单函数调用 |
| B4xx | 黑名单导入 |
| B5xx | 加密相关 |
| B6xx | 注入攻击 |
| B7xx | XSS攻击 |
High-Priority Checks to Always Enforce
需始终强制执行的高优先级检查
Hardcoded secrets (B105, B106, B107) — passwords assigned to variables, passed as function arguments, or set as default parameters.
Injection (B602, B608) — shell injection via with , SQL injection via hardcoded SQL string construction.
subprocessshell=TrueWeak cryptography (B324, B501–B505) — MD5/SHA1 use, disabled TLS certificate validation, weak SSL versions, short cryptographic keys.
Unsafe deserialization (B301, B302, B303, B304) — , , without .
picklemarshalyaml.load()LoaderTemplate injection (B701, B703, B704) — Jinja2 autoescape disabled, Django , MarkupSafe XSS.
mark_safe硬编码密钥(B105、B106、B107) — 赋值给变量、作为函数参数传递或设为默认参数的密码。
注入攻击(B602、B608) — 通过配合实现的Shell注入,通过硬编码SQL字符串构造实现的SQL注入。
subprocessshell=True弱加密(B324、B501–B505) — 使用MD5/SHA1、禁用TLS证书验证、弱SSL版本、短加密密钥。
不安全的反序列化(B301、B302、B303、B304) — 使用、、未指定的。
picklemarshalLoaderyaml.load()模板注入(B701、B703、B704) — Jinja2自动转义禁用、Django的、MarkupSafe XSS。
mark_safeCommon Findings and Fixes
常见检测结果及修复方案
B101 — assert_used
Asserts are stripped in optimized mode (). Never use for security-critical checks.
python -Oassertpython
undefinedB101 — 使用assert
在优化模式()下,assert语句会被移除。绝不要将assert用于安全相关的关键检查。
python -Opython
undefinedBad
错误写法
assert user.is_admin, "Not authorized"
assert user.is_admin, "Not authorized"
Good
正确写法
if not user.is_admin:
raise PermissionError("Not authorized")
**B105/B106/B107 — Hardcoded password**
```pythonif not user.is_admin:
raise PermissionError("Not authorized")
**B105/B106/B107 — 硬编码密码**
```pythonBad
错误写法
password = "hunter2"
connect(password="secret")
password = "hunter2"
connect(password="secret")
Good — read from environment or secrets manager
正确写法 — 从环境变量或密钥管理工具中读取
import os
password = os.environ["DB_PASSWORD"]
**B324 — Weak hash (MD5/SHA1)**
```pythonimport os
password = os.environ["DB_PASSWORD"]
**B324 — 弱哈希算法(MD5/SHA1)**
```pythonBad
错误写法
import hashlib
hashlib.md5(data)
import hashlib
hashlib.md5(data)
Good — use SHA-256 or higher for security contexts
正确写法 — 安全场景下使用SHA-256或更高版本
hashlib.sha256(data)
hashlib.sha256(data)
If MD5 is for non-security use (checksums), suppress with comment:
如果MD5用于非安全场景(如校验和),可添加注释抑制告警:
hashlib.md5(data).hexdigest() # nosec B324 — used for cache key, not security
**B506 — yaml.load()**
```pythonhashlib.md5(data).hexdigest() # nosec B324 — 用于缓存键,非安全用途
**B506 — 使用yaml.load()**
```pythonBad — arbitrary code execution risk
错误写法 — 存在任意代码执行风险
import yaml
yaml.load(data)
import yaml
yaml.load(data)
Good
正确写法
yaml.safe_load(data)
yaml.safe_load(data)
or
或
yaml.load(data, Loader=yaml.SafeLoader)
**B602 — subprocess with shell=True**
```pythonyaml.load(data, Loader=yaml.SafeLoader)
**B602 — subprocess配合shell=True**
```pythonBad — shell injection vector
错误写法 — 存在Shell注入风险
subprocess.Popen(user_input, shell=True)
subprocess.Popen(user_input, shell=True)
Good — pass args as a list, avoid shell
正确写法 — 将参数以列表形式传递,避免使用shell
subprocess.Popen(["ls", "-l", path])
**B608 — Hardcoded SQL**
```pythonsubprocess.Popen(["ls", "-l", path])
**B608 — 硬编码SQL语句**
```pythonBad
错误写法
query = "SELECT * FROM users WHERE name = '" + name + "'"
query = "SELECT * FROM users WHERE name = '" + name + "'"
Good — use parameterized queries
正确写法 — 使用参数化查询
cursor.execute("SELECT * FROM users WHERE name = ?", (name,))
**B501 — No certificate validation**
```pythoncursor.execute("SELECT * FROM users WHERE name = ?", (name,))
**B501 — 未验证证书**
```pythonBad
错误写法
requests.get(url, verify=False)
requests.get(url, verify=False)
Good
正确写法
requests.get(url) # verify=True by default
requests.get(url, verify="/path/to/ca-bundle.crt")
undefinedrequests.get(url) # 默认开启verify=True
requests.get(url, verify="/path/to/ca-bundle.crt")
undefinedSeverity Triage Workflow
严重程度分级处理流程
- Run Bandit with JSON output format and save results to a file (see Output Formats section above).
- Fix all HIGH severity + HIGH confidence findings first — these are near-certain vulnerabilities.
- Evaluate MEDIUM severity findings for false positives; suppress with documented if safe.
# nosec - Decide team policy on LOW severity — consider skipping known false-positive-heavy tests via .
skips - Establish a baseline for legacy codebases to avoid alert fatigue during adoption.
- 使用JSON格式运行Bandit并将结果保存至文件(详见上文输出格式部分)。
- 优先修复所有严重级别为HIGH且置信度为HIGH的结果 — 这些几乎可以确定是漏洞。
- 评估严重级别为MEDIUM的结果是否为误报;若确认安全,添加带说明的标记进行抑制。
# nosec - 针对严重级别为LOW的结果制定团队策略 — 可考虑通过参数跳过已知误报率高的测试项。
skips - 为遗留代码库建立基线,避免在引入工具时产生过多告警导致疲劳。
Additional Resources
额外资源
- — Complete B-code listing with severity, description, and fix pattern per plugin
references/plugin-reference.md - — Pre-commit hooks, GitHub Actions, and baseline automation workflows
references/ci-cd-integration.md
- — 完整的B代码列表,包含每个插件的严重级别、描述及修复方案
references/plugin-reference.md - — 预提交钩子、GitHub Actions及基线自动化工作流的相关内容
references/ci-cd-integration.md