python-bandit

Python Bandit Security Scanning

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "python-bandit" with this command: npx skills add the-perfect-developer/the-perfect-opencode/the-perfect-developer-the-perfect-opencode-python-bandit

Python Bandit Security Scanning

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).

Installation

Install the base package or add extras for specific features:

Base installation

pip install bandit

With TOML config support (pyproject.toml)

pip install "bandit[toml]"

With SARIF output (for GitHub Advanced Security)

pip install "bandit[sarif]"

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.

Core Usage

Scan a full project tree:

bandit -r path/to/project/

Scan with severity filter (report only HIGH):

bandit -r . --severity-level high

or shorthand: -lll (high), -ll (medium+), -l (low+)

bandit -r . -lll

Scan with confidence filter:

bandit -r . --confidence-level high

shorthand: -iii (high), -ii (medium+), -i (low+)

Target specific test IDs only:

bandit -r . -t B105,B106,B107 # hardcoded password checks only

Skip specific test IDs:

bandit -r . -s B101 # skip assert_used (common in tests)

Use a named profile:

bandit examples/*.py -p ShellInjection

Scan from stdin:

cat myfile.py | bandit -

Show N lines of context per finding:

bandit -r . -n 3

Configuration

pyproject.toml (Recommended)

Centralize Bandit settings alongside other tooling:

[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:

bandit -c pyproject.toml -r .

.bandit (INI — auto-discovered with -r)

[bandit] exclude = tests,migrations skips = B101,B601 tests = B201,B301

Bandit auto-discovers .bandit when invoked with -r . No -c flag needed.

YAML Config

exclude_dirs: ['tests', 'path/to/file'] tests: ['B201', 'B301'] skips: ['B101', 'B601']

Override plugin-specific defaults

try_except_pass: check_typed_exception: true

Run: bandit -c bandit.yaml -r .

Generate a Config Template

bandit-config-generator > bandit.yaml

Then edit — remove sections you don't need, adjust defaults

Suppressing False Positives

Mark individual lines with # nosec to suppress all findings:

self.process = subprocess.Popen('/bin/echo', shell=True) # nosec

Suppress specific test IDs only (preferred — avoids hiding future issues):

self.process = subprocess.Popen('/bin/ls *', shell=True) # nosec B602, B607

Use the full test name as an alternative to the ID:

assert yaml.load("{}") == [] # nosec assert_used

Always add a comment explaining why the suppression is justified.

Output Formats

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 # YAML

Baseline Workflow

Use baselines to track only new issues, ignoring pre-existing findings:

1. Generate a baseline from the current state of the codebase

bandit -r . -f json -o .bandit-baseline.json

2. Commit the baseline to version control

git add .bandit-baseline.json

3. Future scans compare against the baseline

bandit -r . -b .bandit-baseline.json

Useful when adopting Bandit on an existing codebase — block only newly introduced issues.

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

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 subprocess with shell=True , SQL injection via hardcoded SQL string construction.

Weak cryptography (B324, B501–B505) — MD5/SHA1 use, disabled TLS certificate validation, weak SSL versions, short cryptographic keys.

Unsafe deserialization (B301, B302, B303, B304) — pickle , marshal , yaml.load() without Loader .

Template injection (B701, B703, B704) — Jinja2 autoescape disabled, Django mark_safe , MarkupSafe XSS.

Common Findings and Fixes

B101 — assert_used

Asserts are stripped in optimized mode (python -O ). Never use assert for security-critical checks.

Bad

assert user.is_admin, "Not authorized"

Good

if not user.is_admin: raise PermissionError("Not authorized")

B105/B106/B107 — Hardcoded password

Bad

password = "hunter2" connect(password="secret")

Good — read from environment or secrets manager

import os password = os.environ["DB_PASSWORD"]

B324 — Weak hash (MD5/SHA1)

Bad

import hashlib hashlib.md5(data)

Good — use SHA-256 or higher for security contexts

hashlib.sha256(data)

If MD5 is for non-security use (checksums), suppress with comment:

hashlib.md5(data).hexdigest() # nosec B324 — used for cache key, not security

B506 — yaml.load()

Bad — arbitrary code execution risk

import yaml yaml.load(data)

Good

yaml.safe_load(data)

or

yaml.load(data, Loader=yaml.SafeLoader)

B602 — subprocess with shell=True

Bad — shell injection vector

subprocess.Popen(user_input, shell=True)

Good — pass args as a list, avoid shell

subprocess.Popen(["ls", "-l", path])

B608 — Hardcoded SQL

Bad

query = "SELECT * FROM users WHERE name = '" + name + "'"

Good — use parameterized queries

cursor.execute("SELECT * FROM users WHERE name = ?", (name,))

B501 — No certificate validation

Bad

requests.get(url, verify=False)

Good

requests.get(url) # verify=True by default requests.get(url, verify="/path/to/ca-bundle.crt")

Severity 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 # nosec if safe.

  • 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.

Additional Resources

  • references/plugin-reference.md — Complete B-code listing with severity, description, and fix pattern per plugin

  • references/ci-cd-integration.md — Pre-commit hooks, GitHub Actions, and baseline automation workflows

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

python-pip-audit

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

turso-libsql

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

git-hooks

No summary provided by upstream source.

Repository SourceNeeds Review