Introduction
Bandit is a security-focused static analysis tool for Python code, originally developed by the OpenStack Security Project. It processes each Python file's AST to identify common security anti-patterns like hardcoded credentials, use of unsafe functions, and injection vulnerabilities.
What Bandit Does
- Scans Python source files for known security anti-patterns using AST analysis
- Detects hardcoded passwords, SQL injection, shell injection, and insecure crypto usage
- Assigns severity and confidence ratings to each finding
- Outputs results in multiple formats including JSON, CSV, HTML, and SARIF
- Integrates into CI/CD pipelines as a pre-merge security gate
Architecture Overview
Bandit parses each Python file into an abstract syntax tree and walks every node through a set of test plugins. Each plugin checks for a specific vulnerability class (e.g., B101 for assert usage, B608 for SQL injection). The node visitor pattern means adding new checks requires only writing a small plugin function and registering it. Results are aggregated with severity/confidence scores and formatted for the chosen output target.
Self-Hosting & Configuration
- Install with
pip install banditand run against any Python project - Create a
.banditorbandit.yamlconfig file to skip specific tests or paths - Use
--skip B101,B601to suppress known false positives in your codebase - Set confidence and severity thresholds with
-ll(low) to-iii(high) filters - Add to pre-commit hooks with the
banditentry in.pre-commit-config.yaml
Key Features
- Over 40 built-in security test plugins covering OWASP top risks in Python
- SARIF output integrates directly with GitHub Code Scanning and IDE security views
- Profile system groups tests into named sets for different scanning scenarios
- Baseline mode compares against a previous run to show only new issues
- Plugin architecture allows custom checks without modifying Bandit itself
Comparison with Similar Tools
- Semgrep — multi-language security scanner with custom rule DSL, broader scope
- Pylint — general code quality linter, not focused on security vulnerabilities
- Safety — checks installed dependencies for known CVEs, not source code
- Snyk Code — commercial SAST with broader language coverage
- Ruff — fast linter focused on style and correctness, not security patterns
FAQ
Q: Does Bandit catch all Python security issues? A: No. Bandit detects common patterns statically but cannot find logic vulnerabilities, runtime issues, or complex data-flow injection chains. Pair it with dynamic testing and dependency scanning for comprehensive coverage.
Q: How do I handle false positives?
A: Use # nosec comments on specific lines, skip tests globally with --skip, or create a baseline file so only new findings are reported.
Q: Can Bandit scan Django or Flask apps specifically? A: Bandit scans all Python code generically. It catches framework-agnostic issues like SQL string formatting and shell calls. Framework-specific checks (like Django template injection) are not included by default.
Q: How do I add Bandit to GitHub Actions?
A: Add a workflow step that runs bandit -r src/ -f sarif -o results.sarif followed by the github/codeql-action/upload-sarif action to display findings in the Security tab.