mrkeyoor.com_
Sat 08 Aug 17:41 UTC
PyPISecurityupdated 08 Aug 2026

bandit

Bandit is a static security checker for Python source. It parses each file into Python's abstract syntax tree, runs security-focused plugins against relevant nodes, and reports findings with test IDs, severity, confidence, source context, and machine-readable formats. It catches recognizable dangerous calls and configurations such as weak hashes, risky subprocess use, unsafe deserialization, hard-coded secrets, and insecure TLS choices. It is a fast lint layer, not proof that an application is secure.

Verdict

Bandit is worth adding as one cheap Python security signal, especially when CI records explicit rule IDs and scoped suppressions. Do not sell a green Bandit run as a security review or a replacement for dependency, secret, and data-flow analysis.

API stability4/5The command-line model, B-series test IDs, severity and confidence levels, `# nosec`, profiles, JSON baselines, and plugin architecture are established and scriptable. Output details and individual rule behavior can evolve as Python changes, and optional formatters have separate extras. Pinning the tool and gating on explicit rule IDs gives a more stable CI contract than parsing human-readable text.
Docs4/5Read the Docs covers installation, recursive scans, thresholds, profiles, stdin, JSON baselines, pre-commit, YAML, TOML and INI configuration, targeted suppressions, config generation, plugins, formatters, and every test rule. The distinctions among config formats are documented but easy to miss, and examples are spread across start, configuration, plugin, and formatter sections rather than one recommended CI recipe.
Maintenance4/5Version 1.9.4 was released in February 2026, the repository was pushed in August 2026, and PyCQA stewardship gives the project an established home. GitHub reports 259 open issues and pull requests with 8,201 stars, a substantial queue but not an inactivity signal. Current Python support, signed multi-architecture container images, and recent releases show continuing maintenance.
Ecosystem5/5Bandit recorded 6,980,352 downloads in the latest measured week, integrates with pre-commit and common CI systems, emits JSON and optional SARIF, and has rule mappings reused by broader linters such as Ruff. PyCQA ownership and stable B identifiers make findings easy to discuss across tools. It is a Python-only ecosystem component and must be paired with dependency and secret scanners.

Use it if

  • You want a low-cost Python security check in pre-commit and CI
  • Your team can review stable B-series rule IDs and record narrow suppressions
  • You need JSON or SARIF output for baselines and code-scanning systems
  • You want to write or configure AST plugins for organization-specific insecure patterns
Skip it if

Setup reality

Install with `pip install bandit`; version 1.9.4 requires Python 3.10 or later and brings PyYAML, stevedore, Rich, plus Colorama on Windows. Basic use is `bandit -r src`, but a useful rollout starts by choosing what counts as a failure. Severity and confidence are separate thresholds, so decide both rather than assuming high severity implies high confidence. Configuration can live in YAML, TOML, or an INI section, but the keys differ: INI uses `exclude`, while YAML and TOML use `exclude_dirs`; the config path is not always auto-discovered, so pass `-c pyproject.toml` or `-c bandit.yaml` explicitly. When pre-commit uses a TOML config, the documented hook must receive the `-c` argument and any needed TOML dependency. Baselines accept only Bandit's JSON output and can hide existing findings while new work is gated, but stale baselines turn into permanent debt. SARIF and baseline commands have optional extras, `bandit[sarif]` and `bandit[baseline]`. Suppressions should say `# nosec B602, B607`, not a blanket marker, and reviews should verify the justification. Excluding all tests may remove noisy `assert` findings but also misses risky fixtures and helpers. Pin the tool independently from application runtime dependencies, upload reports as CI artifacts, and remember that a passing AST scan says nothing about vulnerable third-party packages, leaked credentials, authorization bugs, or dynamic code paths.

Patterns

Scan a Python package recursivelyscan-source-tree

bandit -r src

Recursive mode is required for directories; scope the target to maintained source rather than scanning virtual environments and generated files.

Fail CI on high-severity, high-confidence findingsset-ci-thresholds

bandit -r src --severity-level high --confidence-level high

Severity and confidence are independent filters; this fast gate should complement a broader report reviewed outside the critical path.

Configure targets and skipped tests in YAMLconfigure-yaml

# bandit.yaml
exclude_dirs:
  - tests
  - .venv
tests:
  - B201
  - B301
skips:
  - B101

# run it
bandit -c bandit.yaml -r .

YAML and TOML use `exclude_dirs`; INI configuration uses the different key `exclude`.

Read configuration from pyproject.tomlconfigure-pyproject

# pyproject.toml
[tool.bandit]
exclude_dirs = ['tests', '.venv']
skips = ['B101']

# Bandit requires the path explicitly
bandit -c pyproject.toml -r src

Do not assume pyproject.toml is discovered automatically; pass it with `-c`.

Run only selected tests and skip oneselect-rule-set

bandit -r src -t B301,B302,B303 -s B302

Command-line test and skip lists combine with config lists; putting the same ID in both config lists is an error.

Suppress only justified rule IDssuppress-specific-finding

process = subprocess.Popen(
    ['/trusted/tool', '--version'],
    shell=False,
)  # nosec B603

Name the exact test instead of bare `# nosec`, and require a review comment explaining why the flagged pattern is safe here.

Create and apply a JSON baselinecreate-baseline

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

Only JSON reports are accepted as baselines; schedule cleanup or known findings can remain hidden indefinitely.

Produce SARIF for a code-scanning platformemit-sarif

python -m pip install 'bandit[sarif]'
bandit -r src -f sarif -o bandit.sarif

SARIF support is an optional extra, so add it to the pinned CI tool environment rather than relying on a developer machine.

Run Bandit through pre-commitrun-pre-commit

repos:
  - repo: https://github.com/PyCQA/bandit
    rev: 1.9.4
    hooks:
      - id: bandit
        args: ['-c', 'pyproject.toml', '-r', 'src']

Pin the hook revision and pass the config path explicitly so local and CI scans use the same policy.

Scan Python source from standard inputscan-standard-input

git show HEAD:src/legacy.py | bandit -

Stdin is useful for generated or historical content, but path-based exclusions and filenames are no longer available to the scan.

Generate a complete starter configurationgenerate-config

bandit-config-generator -o bandit.yaml

The generator includes defaults for detected test and blacklist plugins; delete untouched sections to keep the reviewed policy understandable.

Scan with the official container imagerun-container-image

docker run --rm -v "$PWD:/code:ro" ghcr.io/pycqa/bandit/bandit:latest -r /code/src

The project publishes signed images for several architectures, but production CI should pin an immutable version or digest instead of `latest`.

Alternatives

PackageRegistryPick it when
semgrepPyPIYou need multi-language rules and deeper pattern matching across a polyglot repository
ruffPyPIYou want very fast Python linting with Flake8 Bandit-derived S rules in one tool
pylintPyPIYou need broad Python correctness and design analysis with a smaller security component