security-practices
Security best practices for Python development. Activated when working with security concerns, input validation, injection prevention, or threat modeling.
When & Why to Use This Skill
This Claude skill serves as a comprehensive security consultant for Python development, focusing on 'secure by default' principles and defense-in-depth strategies. It provides actionable guidance and code patterns for critical security tasks including robust input validation, path traversal prevention, and command injection mitigation. By integrating OWASP standards and threat modeling practices, it helps developers and security teams build resilient applications, manage sensitive data securely, and prevent information leakage throughout the software development lifecycle.
Use Cases
- Implementing strict input validation and sanitization for user-provided strings and identifiers to prevent injection attacks.
- Securing file system operations by validating paths and filenames to prevent directory traversal vulnerabilities.
- Executing system commands safely using the subprocess module to eliminate risks associated with shell injection.
- Managing sensitive credentials and environment variables while ensuring error messages do not leak internal system details.
- Conducting security-focused code reviews and proactive threat modeling to identify potential attack vectors during the design phase.
| name | security-practices |
|---|---|
| description | Security best practices for Python development. Activated when working with security concerns, input validation, injection prevention, or threat modeling. |
Security practices
Purpose
Comprehensive guide for security in Python projects including input validation, injection prevention, secure defaults, and threat modeling.
When to use
This skill activates when:
- Validating user input
- Handling file paths
- Executing system commands
- Working with sensitive data
- Reviewing code for vulnerabilities
- Designing security architecture
Core principles
Secure by default
- Default configuration should be the secure configuration
- Require explicit opt-in for less secure behavior
- Validate input at system boundaries
Defense in depth
- Use multiple layers of validation
- Never rely on a single security control
- Validate at multiple levels
Input validation
String input validation
import re
def validate_identifier(value: str) -> str:
"""Validate identifier string."""
if not value:
raise ValueError("Identifier cannot be empty")
if not re.match(r'^[a-zA-Z][a-zA-Z0-9_]*$', value):
raise ValueError(f"Invalid identifier: {value}")
if len(value) > 255:
raise ValueError("Identifier too long")
return value
def sanitize_for_display(value: str) -> str:
"""Sanitize string for safe display."""
# Remove control characters
return ''.join(c for c in value if c.isprintable() or c in '\n\t')
Path validation
from pathlib import Path
def validate_path(user_path: str, allowed_base: Path) -> Path:
"""Validate path is within allowed directory."""
# Resolve to absolute path
path = (allowed_base / user_path).resolve()
# Check path is within allowed base
if not path.is_relative_to(allowed_base):
raise ValueError("Path traversal detected")
return path
def validate_filename(filename: str) -> str:
"""Validate filename is safe."""
# Check for path separators
if '/' in filename or '\\' in filename:
raise ValueError("Invalid filename: contains path separator")
# Check for special names
if filename in ('.', '..'):
raise ValueError("Invalid filename: special directory name")
# Check for null bytes
if '\x00' in filename:
raise ValueError("Invalid filename: contains null byte")
return filename
Command injection prevention
Safe command execution
import subprocess
import shlex
def run_safe_command(args: list[str]) -> subprocess.CompletedProcess:
"""Run command safely without shell."""
# Never use shell=True with user input
return subprocess.run(
args,
capture_output=True,
text=True,
timeout=30,
check=True,
)
# Good: List of arguments
run_safe_command(['git', 'log', '--oneline', '-n', '10'])
# BAD: Never do this with user input
# subprocess.run(f"git log {user_input}", shell=True) # DANGEROUS
Quote user input
import shlex
def quote_for_shell(value: str) -> str:
"""Quote value for safe shell usage."""
return shlex.quote(value)
# Usage
filename = quote_for_shell(user_provided_filename)
Sensitive data handling
Environment variables
import os
def get_secret(name: str) -> str:
"""Get secret from environment."""
value = os.environ.get(name)
if value is None:
raise ValueError(f"Required secret not set: {name}")
return value
# Never log secrets
def process_with_secret(data: str) -> None:
secret = get_secret("API_KEY")
# Use secret, never print/log it
result = call_api(data, auth=secret)
Avoid information leakage
class SafeError(Exception):
"""Error with safe message for users."""
def __init__(self, user_message: str, internal_details: str | None = None):
super().__init__(user_message)
self._internal = internal_details
@property
def internal_details(self) -> str | None:
"""Details for logging only, never expose to users."""
return self._internal
def process_request(data: dict) -> Result:
try:
return _process_impl(data)
except DatabaseError as e:
# Log full error internally
logger.error(f"Database error: {e}")
# Return safe message to user
raise SafeError("Processing failed", str(e)) from e
OWASP considerations
Injection flaws
- Never interpolate user input into commands
- Use parameterized queries for databases
- Validate and sanitize all input
Authentication
- Use secure password hashing (bcrypt, argon2)
- Implement rate limiting
- Use secure session management
Sensitive data exposure
- Never log sensitive data
- Encrypt data at rest and in transit
- Use environment variables for secrets
Security checklist
Before completing security-sensitive code:
- All user input validated
- No command injection vectors
- No path traversal vectors
- Secrets not logged or exposed
- Error messages don't leak internals
- Using latest dependency versions
- Following principle of least privilege
Threat modeling
When designing features, consider:
- What could go wrong? - Identify attack vectors
- What are we doing about it? - Document mitigations
- Did we do a good job? - Verify implementation
- Can we do better? - Continuous improvement
Additional resources: