Documentation

Python Security Checks

These checks identify security vulnerabilities specific to Python code, including unsafe deserialization, code injection, and other Python-specific risks.

python-rce-eval

Severity: Critical

What It Detects

Use of eval() or exec() functions in Python.

Why It's Dangerous

Python's eval() and exec() execute arbitrary code, allowing attackers to run any Python code on your server.

Example Vulnerable Code

# User input executed as code
user_input = request.args.get('expression')
result = eval(user_input)  # DANGEROUS!
 
# Dynamic code execution
code = request.json.get('code')
exec(code)  # EXTREMELY DANGEROUS!

Safe Alternative

# For math expressions
import ast
def safe_eval(expr):
    # Only allow literals and basic operations
    return ast.literal_eval(expr)
 
# For JSON
import json
data = json.loads(user_input)
 
# For configuration
import yaml
config = yaml.safe_load(config_string)

python-rce-subprocess

Severity: Critical

What It Detects

Use of subprocess module with shell=True or user-controlled commands.

Why It's Dangerous

Shell execution allows command injection through special characters like ;, |, &&.

Example Vulnerable Code

import subprocess
 
# shell=True enables command injection
subprocess.run(f"ls {user_dir}", shell=True)  # DANGEROUS!
 
# User-controlled command
subprocess.run(user_command, shell=True)  # EXTREMELY DANGEROUS!

Safe Alternative

import subprocess
import shlex
 
# Use list arguments (no shell interpretation)
subprocess.run(["ls", sanitized_dir])
 
# If shell is needed, use shlex
safe_cmd = shlex.quote(user_input)
subprocess.run(f"command {safe_cmd}", shell=True)

python-rce-os-system

Severity: Critical

What It Detects

Use of os.system() or os.popen().

Why It's Dangerous

These functions execute shell commands and are vulnerable to injection.

Example Vulnerable Code

import os
 
os.system(f"rm {filename}")  # DANGEROUS!
os.popen(f"cat {filepath}")  # DANGEROUS!

Safe Alternative

import os
import shutil
 
# Use Python's built-in functions
os.remove(safe_filename)
shutil.rmtree(safe_directory)
 
# For file reading
with open(safe_filepath) as f:
    content = f.read()

python-rce-pickle

Severity: High

What It Detects

Use of pickle.load() or pickle.loads() which can execute arbitrary code during deserialization.

Why It's Dangerous

Pickle can execute arbitrary Python code when loading data, making it unsafe for untrusted input.

Example Vulnerable Code

import pickle
 
# Loading untrusted pickle data
data = pickle.loads(user_data)  # DANGEROUS!
 
with open(untrusted_file, 'rb') as f:
    obj = pickle.load(f)  # DANGEROUS!

Safe Alternative

import json
 
# Use JSON for untrusted data
data = json.loads(user_data)
 
# Or use restricted unpickler
import pickle
import io
 
class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        raise pickle.UnpicklingError("Restricted")
 
def safe_pickle_load(data):
    return RestrictedUnpickler(io.BytesIO(data)).load()

python-rce-yaml

Severity: High

What It Detects

Use of yaml.load() without Loader=SafeLoader or yaml.safe_load().

Why It's Dangerous

YAML's default loader can instantiate arbitrary Python objects, leading to code execution.

Example Vulnerable Code

import yaml
 
# Unsafe YAML loading
data = yaml.load(user_input)  # DANGEROUS!
data = yaml.load(user_input, Loader=yaml.Loader)  # DANGEROUS!

Safe Alternative

import yaml
 
# Use safe_load
data = yaml.safe_load(user_input)
 
# Or explicitly use SafeLoader
data = yaml.load(user_input, Loader=yaml.SafeLoader)

python-injection-sql

Severity: High

What It Detects

SQL queries built with string concatenation or f-strings.

Why It's Dangerous

SQL injection can allow attackers to read, modify, or delete database data.

Example Vulnerable Code

# String concatenation
query = "SELECT * FROM users WHERE id = " + user_id
cursor.execute(query)  # DANGEROUS!
 
# f-strings
query = f"SELECT * FROM users WHERE name = '{name}'"
cursor.execute(query)  # DANGEROUS!

Safe Alternative

# Use parameterized queries
cursor.execute(
    "SELECT * FROM users WHERE id = %s",
    (user_id,)
)
 
# With SQLAlchemy
from sqlalchemy import text
result = session.execute(
    text("SELECT * FROM users WHERE id = :id"),
    {"id": user_id}
)

python-secrets-hardcoded

Severity: Critical

What It Detects

Hardcoded credentials in Python code:

  • API keys
  • Passwords
  • Secret keys

Example Vulnerable Code

API_KEY = "sk-abc123..."  # DANGEROUS!
PASSWORD = "super_secret"  # DANGEROUS!

Safe Alternative

import os
 
API_KEY = os.environ.get("API_KEY")
PASSWORD = os.environ.get("DB_PASSWORD")

Other Python Checks

| Check | Severity | Description | |-------|----------|-------------| | python-rce-marshal | Medium | marshal module usage | | python-rce-dynamic-import | High | __import__ or importlib | | python-network-ssl-disabled | High | SSL verification disabled | | python-fs-tempfile | Medium | Insecure temp file creation | | python-fs-path-traversal | High | Path traversal patterns |

Summary

| Check | Severity | Key Fix | |-------|----------|---------| | python-rce-eval | Critical | Use ast.literal_eval or JSON | | python-rce-subprocess | Critical | Use list arguments, no shell | | python-rce-os-system | Critical | Use built-in Python functions | | python-rce-pickle | High | Use JSON or RestrictedUnpickler | | python-rce-yaml | High | Use yaml.safe_load | | python-injection-sql | High | Use parameterized queries | | python-secrets-hardcoded | Critical | Use environment variables |

Next Steps