7.2 KiB
Security Guide
CQaS incorporates comprehensive security analysis capabilities designed to identify potential vulnerabilities and security anti-patterns in Python code. The security analysis engine uses static analysis techniques combined with pattern matching to detect common security issues before they reach production.
Security Analysis Features
- Multi-category Vulnerability Detection: 8 distinct vulnerability types
- CVSS v3.1 Scoring: Industry-standard severity assessment
- Confidence Ratings: Reliability assessment for each finding
- Context-aware Analysis: Understanding of Python-specific security patterns
- False Positive Reduction: Smart filtering to minimise noise
- Actionable Remediation: Specific guidance for fixing issues
Analysis Scope
The security analyser examines:
- Function calls and method invocations
- String literals and formatting operations
- Import statements and module usage
- Data serialisation and deserialisation
- Template and code generation patterns
- Cryptographic function usage
- Input validation and sanitisation
Vulnerability Categories
1. SQL Injection (CVSS Base: 8.1)
SQL injection vulnerabilities occur when user input is directly incorporated into SQL queries without proper sanitisation.
Detection Patterns
# Detected patterns
sql_query = f"SELECT * FROM users WHERE id = {user_id}" # High risk
query = "SELECT * FROM table WHERE name = '" + name + "'" # High risk
cursor.execute("DELETE FROM users WHERE id = %s" % user_id) # High risk
Safe Alternatives
# Parameterized queries (safe)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
cursor.execute("SELECT * FROM users WHERE id = %(id)s", {"id": user_id})
# Using ORM (safe)
User.objects.filter(id=user_id)
CQaS Detection Logic
- Pattern matching for SQL keywords with string formatting
- Detection of string concatenation in SQL contexts
- Identification of
.format()
usage with SQL strings - F-string usage with SQL operations
2. Command Injection (CVSS Base: 9.8)
Command injection allows attackers to execute arbitrary system commands through application vulnerabilities.
High-Risk Functions
# Dangerous patterns detected
os.system(f"ls {user_input}") # Critical
subprocess.call(command, shell=True) # High risk
subprocess.run(cmd, shell=True) # High risk
subprocess.Popen(command, shell=True) # High risk
os.popen(f"grep {pattern} file.txt") # High risk
Safe Alternatives
# Safe command execution
subprocess.run(["ls", directory], capture_output=True) # Safe
subprocess.call(["grep", pattern, "file.txt"]) # Safe
# Input validation and sanitisation
import shlex
safe_command = shlex.quote(user_input)
3. Code Injection (CVSS Base: 9.3)
Code injection vulnerabilities allow execution of arbitrary Python code.
Dangerous Functions
# Critical security risks
eval(user_input) # Critical
exec(user_code) # Critical
compile(source, filename, mode) # High risk
# Dynamic attribute access
getattr(obj, user_attr) # Medium risk
setattr(obj, user_attr, value) # Medium risk
Safe Alternatives
# Safe evaluation alternatives
import ast
def safe_eval(expr):
return ast.literal_eval(expr) # Only evaluates literals
# Whitelist-based attribute access
ALLOWED_ATTRS = {'name', 'email', 'age'}
if attr_name in ALLOWED_ATTRS:
getattr(obj, attr_name)
4. Hardcoded Secrets (CVSS Base: 7.5)
Hardcoded secrets in source code pose significant security risks.
Detection Patterns
# Detected secret patterns
password = "admin123" # Detected
api_key = "sk-1234567890abcdef" # Detected
secret_token = "eyJhbGciOiJIUzI1NiJ9..." # Detected
db_password = "MySecretPassword123" # Detected
# Base64 encoded secrets
encoded_secret = "YWRtaW46cGFzc3dvcmQ=" # Detected
# Hex patterns
hex_key = "deadbeef12345678" # Detected if long enough
Best Practices
# Environment variables (recommended)
import os
password = os.getenv('DB_PASSWORD')
api_key = os.environ['API_KEY']
# Configuration files (not in version control)
import configparser
config = configparser.ConfigParser()
config.read('secrets.ini')
secret = config['DEFAULT']['secret_key']
# Key management services
from azure.keyvault.secrets import SecretClient
secret = client.get_secret("database-password").value
5. Weak Cryptography (CVSS Base: 7.4)
Usage of cryptographically weak algorithms or insecure random number generation.
Weak Algorithms Detected
# Weak hash functions
import hashlib
md5_hash = hashlib.md5(data) # Vulnerable
sha1_hash = hashlib.sha1(data) # Vulnerable
# Insecure random
import random
token = random.random() # Not cryptographically secure
session_id = random.randint(1000, 9999) # Predictable
Secure Alternatives
# Strong hash functions
import hashlib
sha256_hash = hashlib.sha256(data) # Secure
sha3_hash = hashlib.sha3_256(data) # Secure
# Cryptographically secure random
import secrets
token = secrets.token_urlsafe(32) # Secure
random_bytes = secrets.randbits(256) # Secure
# Password hashing
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
6. Dangerous Imports (CVSS Base: 4.3)
Importing modules that can lead to security vulnerabilities.
Risky Modules
# Deserialisation risks
import pickle # Can execute arbitrary code
import dill # Similar risks to pickle
import shelve # Uses pickle internally
# Command execution
import commands # Deprecated, command injection risk
import popen2 # Command injection risk
Safer Alternatives
# Safe serialisation
import json
data = json.loads(json_string) # Safe for simple data
# Structured data
import xml.etree.ElementTree as ET
root = ET.fromstring(xml_data) # Safer XML parsing
# For complex objects
import marshmallow # Schema validation and serialisation
7. Unsafe Deserialisation (CVSS Base: 8.8)
Deserialising untrusted data can lead to remote code execution.
Dangerous Patterns
# High-risk deserialisation
import pickle
data = pickle.load(file) # Can execute arbitrary code
obj = pickle.loads(user_data) # Critical if user_data is untrusted
# Other risky deserializers
import dill
obj = dill.load(file)
import yaml
data = yaml.load(stream) # Can execute arbitrary Python
Safe Deserialisation
# Safe alternatives
import json
data = json.loads(json_string) # Safe for basic data types
# Safe YAML loading
import yaml
data = yaml.safe_load(stream) # Only loads basic YAML constructs
# Schema validation
from marshmallow import Schema, fields
class UserSchema(Schema):
name = fields.Str(required=True)
email = fields.Email(required=True)
schema = UserSchema()
result = schema.load(untrusted_data) # Validated deserialisation
8. Template Injection (CVSS Base: 8.5)
Server-side template injection can lead to remote code execution.
Risky Template Usage
# String formatting with user input
template = f"Hello {user_input}" # Potential injection
result = "User: {}".format(user_data) # Risk if user_data contains format specifiers
Safe Template Practices
safe_template = f"User: {user_data}"