DEV Community

JEFFERSON ROSAS CHAMBILLA
JEFFERSON ROSAS CHAMBILLA

Posted on

Applying Bandit SAST Tool to Secure Python Applications

Why Bandit for Python Security?

Bandit is an open-source SAST tool developed by the OpenStack Security Project that specializes in analyzing Python code for common security issues. It's particularly valuable because:

  • Python-specific analysis - Understands Python idioms and common patterns
  • Plugin-based architecture - Extensible with custom checks
  • CI/CD friendly - Designed for automation
  • Zero cost - Completely free and open-source

Common Vulnerabilities Bandit Detects

  • SQL injection vulnerabilities
  • Shell injection risks
  • Hardcoded passwords and secrets
  • Use of insecure modules
  • Input validation issues
  • Information disclosure risks

Hands-On: Implementing Bandit

Installation

# Install using pip
pip install bandit

# Or install from source
git clone https://github.com/PyCQA/bandit.git
cd bandit
pip install .
Enter fullscreen mode Exit fullscreen mode

Basic Usage

# Scan a single file
bandit my_script.py

# Scan an entire directory
bandit -r my_project/

# Generate HTML report
bandit -r my_project/ -f html -o report.html

# Scan with specific security level
bandit -r my_project/ -l high
Enter fullscreen mode Exit fullscreen mode

Sample Vulnerable Python Code

# vulnerable_app.py
import os
import pickle
import subprocess
import sqlite3

def process_user_input():
    # Vulnerability: Code injection
    user_input = input("Enter command: ")
    os.system(user_input)  # B602: subprocess_popen_with_shell_equals_true

def database_operations():
    # Vulnerability: SQL injection
    username = input("Enter username: ")
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")  # B608: hardcoded_sql_expressions

def data_deserialization():
    # Vulnerability: Insecure deserialization
    data = input("Enter serialized data: ")
    obj = pickle.loads(data.encode())  # B301: blacklist
Enter fullscreen mode Exit fullscreen mode

Running Bandit Scan

bandit -r vulnerable_app.py -f txt
Enter fullscreen mode Exit fullscreen mode

Sample Bandit Output

Results generated:
>> Issue: [B602:subprocess_popen_with_shell_equals_true] Using subprocess with shell=True
   Severity: High   Confidence: High
   Location: vulnerable_app.py:8
   More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b602-subprocess-popen-with-shell-equals-true
7    user_input = input("Enter command: ")
8    os.system(user_input)

>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Medium
   Location: vulnerable_app.py:15
15    cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")

>> Issue: [B301:blacklist] Use of unsafe deserialization function.
   Severity: High   Confidence: High
   Location: vulnerable_app.py:20
20    obj = pickle.loads(data.encode())
Enter fullscreen mode Exit fullscreen mode

Advanced Bandit Configuration

Custom Configuration File

# bandit.yml
exclude_dirs: ['tests', 'venv', 'migrations']
skips: ['B101', 'B102']
tests: ['B301', 'B302', 'B601', 'B602']

targets:
  - src/
  - app/

output_format: json
verbose: true
Enter fullscreen mode Exit fullscreen mode

Using Configuration File

bandit -c bandit.yml -r my_project/
Enter fullscreen mode Exit fullscreen mode

CI/CD Integration (GitHub Actions)

name: Security Scan with Bandit
on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9'

      - name: Install Bandit
        run: pip install bandit

      - name: Run Bandit Security Scan
        run: bandit -r . -f json -o bandit-report.json

      - name: Upload Bandit Report
        uses: actions/upload-artifact@v3
        with:
          name: bandit-report
          path: bandit-report.json
Enter fullscreen mode Exit fullscreen mode

Bandit Test Types and Severity Levels

Severity Levels

  • Low: Code quality issues, minor security concerns
  • Medium: Potential security vulnerabilities
  • High: Critical security vulnerabilities

Common Test IDs

  • B1xx: Various general tests
  • B2xx: Application/framework-specific issues
  • B3xx: Blacklisted imports and functions
  • B4xx: Using insecure random generators
  • B5xx: SSL/TLS issues
  • B6xx: Shell injection vulnerabilities
  • B7xx: Pickle and YAML deserialization

Custom Bandit Plugins

Creating Custom Tests

# custom_checks.py
import bandit
from bandit.core import test_properties as test

@test.checks('Call')
@test.test_id('B901')
def hardcoded_api_key(context):
    """Check for hardcoded API keys"""
    suspicious_strings = ['api_key', 'secret_key', 'password']
    if context.call_function_name_qual in suspicious_strings:
        return bandit.Issue(
            severity=bandit.HIGH,
            confidence=bandit.MEDIUM,
            text="Potential hardcoded API key detected"
        )
Enter fullscreen mode Exit fullscreen mode

Using Custom Plugins

bandit -r my_project/ -p custom_checks.py
Enter fullscreen mode Exit fullscreen mode

Best Practices for Bandit Implementation

1. Integrate Early in Development

# Pre-commit hook example
# .git/hooks/pre-commit
#!/bin/bash
bandit -r . -l high -i
Enter fullscreen mode Exit fullscreen mode

2. Regular Scheduled Scans

# GitHub Actions scheduled scan
on:
  schedule:
    - cron: '0 2 * * 1'  # Weekly scan
Enter fullscreen mode Exit fullscreen mode

3. Baseline Establishment

# Establish baseline ignoring existing issues
bandit -r . --baseline baseline.json
Enter fullscreen mode Exit fullscreen mode

4. Quality Gates

# Fail build on high severity issues
bandit -r . -l high --exit-zero
Enter fullscreen mode Exit fullscreen mode

Limitations and Considerations

While Bandit is powerful, it's important to understand its limitations:

  • Static analysis only - Cannot detect runtime issues
  • Python-specific - Only works with Python code
  • Pattern-based - May produce false positives/negatives
  • No data flow analysis - Limited context awareness

Conclusion

Bandit provides an excellent open-source SAST solution for Python applications. Its ease of use, comprehensive vulnerability detection, and seamless CI/CD integration make it an essential tool for any Python developer concerned with security.

By implementing Bandit in your development workflow, you can catch common security issues early, reduce remediation costs, and build more secure Python applications.

Top comments (0)