Bandit Security Rules: Complete Python Vulnerability Guide

Bandit Security Rules: Complete Python Vulnerability Guide

When you first run Bandit on a production codebase, you’ll get back a 47-page report filled with cryptic rule numbers like B105, B608, and B301. My initial reaction to that is normally panic, followed by the urge to add # nosec comments everywhere and call it a day. But here’s the thing about security tools-they’re only as good as your understanding of what they’re actually telling you.

Bandit organizes its security checks into logical categories, each targeting different types of vulnerabilities that can creep into Python applications. Think of it as having a security expert looking over your shoulder, pointing out potential issues before they become real problems.

The Big Picture: How Bandit Thinks About Security

Bandit doesn’t just randomly flag code-it’s looking for specific patterns that security researchers have identified as problematic over the years. These patterns fall into several major categories, each representing a different way your application could be compromised.

Password and Secret Detection

The most common security issue Bandit finds? Hardcoded passwords and secrets scattered throughout codebases. I’ve seen everything from database passwords in Django settings files to API keys buried in utility functions.

# B105: Hardcoded password string - Bandit flags this immediately
password = "admin123"
api_key = "sk-1234567890abcdef"  # Also flagged

The problem isn’t just that these secrets are visible in your source code. They’re also stored in your version control history, potentially shared when you open-source code, and can be extracted from compiled Python bytecode. Every hardcoded secret is a ticking time bomb.

Cryptographic Vulnerabilities

Cryptography is one of those areas where doing things wrong is often worse than doing nothing at all. Bandit’s cryptographic rules catch developers using outdated or broken algorithms that give a false sense of security.

import hashlib
# B303: MD5 is cryptographically broken
hashlib.md5(data)  # Flagged - vulnerable to collision attacks

# Secure alternative
hashlib.sha256(data)  # Use SHA-256 instead

MD5 and SHA1 hashing, for example, have been cryptographically broken for years, yet they still appear in codebases with alarming frequency. The same goes for encryption algorithms like DES or 3DES-they’re not just old, they’re fundamentally insecure by modern standards.

Injection Vulnerabilities

SQL injection remains one of the most dangerous and common web application vulnerabilities, and Bandit’s B608 rule specifically looks for the telltale signs: string concatenation or formatting operations that build SQL queries.

The classic mistake looks innocent enough-taking user input and dropping it directly into a query string. But what seems like a simple database lookup can become a gateway for attackers to read, modify, or delete your entire database.

Bandit also watches for shell injection vulnerabilities, where user input gets passed to system commands. These are particularly nasty because they can give attackers direct access to your server’s operating system.

File System Security

File permissions and temporary file handling might seem mundane, but they’re a common source of security issues in production systems. Bandit flags overly permissive file permissions and insecure temporary file usage because these seemingly minor details can expose sensitive data or create opportunities for privilege escalation attacks.

Understanding Severity and Confidence

Here’s where Bandit gets really useful-it doesn’t just tell you what’s wrong, it tells you how wrong it is and how confident it is about that assessment. This two-dimensional approach helps you prioritize fixes intelligently.

High severity issues are the ones that keep security teams awake at night: direct code execution vulnerabilities, fundamentally broken cryptography, and clear pathways for data exfiltration. These are the “drop everything and fix this now” category.

Medium severity issues require additional conditions to be exploited but still represent real security risks. Think hardcoded passwords that aren’t yet in production, or SQL injection patterns that might not be reachable by user input.

Low severity issues are more about security hygiene-weak random number generation, deprecated functions, or patterns that could become problematic if the code evolves in certain directions.

The confidence level tells you how certain Bandit is that it’s found a real issue. High confidence findings are almost certainly problems you need to address. Low confidence findings might be false positives or edge cases worth investigating but not necessarily alarming.

Rule Categories in Practice

Bandit organizes its 100+ rules into several categories based on what they’re looking for:

Import-based rules flag potentially dangerous imports. Sometimes the mere presence of certain modules in your code indicates elevated risk-like importing telnet or pickle without considering the security implications.

Function call rules analyze how you’re using specific functions. Calling eval() with user input is almost always dangerous, while using tempfile.mktemp() instead of more secure alternatives creates race condition vulnerabilities.

AST-based rules look at code structure itself. Using assert statements for security checks is problematic because Python can disable assertions with the -O flag, potentially bypassing your security logic.

The Human Element

What makes Bandit particularly valuable isn’t just its ability to find vulnerabilities-it’s how it helps you think about security. Every finding is an opportunity to ask: “What could go wrong here? How might an attacker abuse this? Is there a more secure way to accomplish the same thing?”

The best security practices often emerge from understanding not just what the rules forbid, but why they forbid it. When Bandit flags string formatting in SQL queries, it’s not being pedantic-it’s protecting you from a class of vulnerabilities that have compromised countless applications over the years.

Making Bandit Work for You

The key to effective Bandit usage isn’t running it once and fixing everything. It’s integrating it into your development workflow so that security becomes a natural part of how you write code. Start with the high-severity, high-confidence findings and work your way down. Use the tool to educate your team about secure coding practices.

Most importantly, don’t treat Bandit as a checkbox to tick. Treat it as a conversation starter about security in your application. The goal isn’t to make Bandit happy-it’s to build applications that are genuinely more secure.

Understanding Bandit’s rules transforms security scanning from a compliance exercise into a learning opportunity. Every rule violation is a chance to write better, more secure code. And in today’s threat landscape, that education is invaluable.

Subscribe to the Newsletter

Get the latest posts and insights delivered straight to your inbox.