Python Patterns

84+ vulnerability patterns for Python applications including Django, Flask, FastAPI, and data science libraries.

Overview

Bloodhound provides comprehensive Python security analysis covering web frameworks, data processing pipelines, and common security anti-patterns.

18
Critical
28
High
22
Medium
16
Low

Injection Vulnerabilities

Critical

SQL Injection

String formatting in SQL queries allows database manipulation.

Vulnerable
Python
1# Vulnerable: String formatting in SQL
2def get_user(user_id):
3 query = f"SELECT * FROM users WHERE id = '{user_id}'"
4 cursor.execute(query)
Secure
Python
1# Secure: Parameterized queries
2def get_user(user_id):
3 query = "SELECT * FROM users WHERE id = %s"
4 cursor.execute(query, (user_id,))
Critical

Command Injection

User input in shell commands enables arbitrary command execution.

Vulnerable
Python
1# Vulnerable: Shell injection via os.system
2import os
3def process_file(filename):
4 os.system(f"cat {filename}")
Secure
Python
1# Secure: Use subprocess with shell=False
2import subprocess
3def process_file(filename):
4 subprocess.run(['cat', filename], shell=False)
Critical

Code Injection (eval)

Using eval() or exec() with user input enables arbitrary code execution.

Vulnerable
Python
1# Vulnerable: eval with user input
2def calculate(expression):
3 return eval(expression) # User could pass "__import__('os').system('rm -rf /')"
Secure
Python
1# Secure: Use ast.literal_eval for safe parsing
2import ast
3def calculate(expression):
4 return ast.literal_eval(expression)

Insecure Deserialization

Critical Risk

Deserialization vulnerabilities in Python often lead to remote code execution. Never deserialize untrusted data with pickle or yaml.load.
Critical

Insecure Pickle Deserialization

Unpickling untrusted data can execute arbitrary code.

Vulnerable
Python
1# Vulnerable: Loading untrusted pickle
2import pickle
3data = pickle.loads(user_input)
Secure
Python
1# Secure: Use JSON or validate source
2import json
3data = json.loads(user_input)
4# Or use hmac to verify pickle integrity
High

YAML Deserialization

PyYAML full_load can instantiate arbitrary Python objects.

Vulnerable
Python
1# Vulnerable: yaml.load without Loader
2import yaml
3data = yaml.load(user_input) # Allows arbitrary code execution
Secure
Python
1# Secure: Use safe_load
2import yaml
3data = yaml.safe_load(user_input)

Path Traversal

High

Path Traversal

User-controlled paths can access files outside intended directories.

Vulnerable
Python
1# Vulnerable: Direct path concatenation
2def read_file(filename):
3 with open(f"/uploads/{filename}") as f:
4 return f.read()
Secure
Python
1# Secure: Validate and normalize paths
2import os
3def read_file(filename):
4 base_path = os.path.abspath("/uploads")
5 file_path = os.path.abspath(os.path.join(base_path, filename))
6 if not file_path.startswith(base_path):
7 raise ValueError("Invalid path")
8 with open(file_path) as f:
9 return f.read()

Django Security

High

Django Template XSS

Using |safe filter or mark_safe with user input bypasses auto-escaping.

Vulnerable
Python
1# Vulnerable: Marking user input as safe
2from django.utils.safestring import mark_safe
3def render_comment(comment):
4 return mark_safe(f"<p>{comment}</p>")
Secure
Python
1# Secure: Let Django auto-escape
2def render_comment(comment):
3 return f"<p>{comment}</p>" # Django escapes in templates
Critical

Django Raw SQL

Raw SQL queries with string formatting bypass ORM protections.

Vulnerable
Python
1# Vulnerable: Raw SQL with formatting
2User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")
Secure
Python
1# Secure: Use parameterized raw queries
2User.objects.raw("SELECT * FROM users WHERE name = %s", [name])

Flask Security

Critical

Flask SSTI

Server-side template injection via render_template_string.

Vulnerable
Python
1# Vulnerable: User input in template string
2from flask import render_template_string
3@app.route('/greet')
4def greet():
5 return render_template_string(f"Hello {request.args.get('name')}")
Secure
Python
1# Secure: Pass variables to template
2@app.route('/greet')
3def greet():
4 return render_template_string("Hello {{ name }}", name=request.args.get('name'))
Critical

Flask Debug Mode in Production

Debug mode exposes Werkzeug debugger allowing RCE.

Vulnerable
Python
1# Vulnerable: Debug mode enabled
2if __name__ == '__main__':
3 app.run(debug=True) # Exposes interactive debugger
Secure
Python
1# Secure: Use environment variable
2if __name__ == '__main__':
3 app.run(debug=os.environ.get('FLASK_DEBUG', False))