rackham-meeting-analyzer/backend/app/core/security.py
2025-11-03 08:15:51 -06:00

84 lines
2.2 KiB
Python

"""
Security utilities for file uploads and validation.
"""
import re
from pathlib import Path
def sanitize_filename(filename: str) -> str:
"""
Sanitize a filename to prevent path traversal and other security issues.
- Removes path separators (/ and \)
- Removes null bytes
- Removes control characters
- Limits to safe characters
- Preserves extension
Args:
filename: Original filename from user
Returns:
Sanitized filename safe for storage
"""
# Get the base name (remove any path components)
filename = Path(filename).name
# Remove any null bytes
filename = filename.replace('\x00', '')
# Remove or replace dangerous characters
# Allow: alphanumeric, dash, underscore, dot, space
filename = re.sub(r'[^\w\s\-\.]', '_', filename)
# Remove multiple dots (except for extension)
parts = filename.rsplit('.', 1)
if len(parts) == 2:
name, ext = parts
name = name.replace('.', '_')
filename = f"{name}.{ext}"
# Remove leading/trailing spaces and dots
filename = filename.strip('. ')
# Ensure filename is not empty
if not filename:
filename = "unnamed_file"
# Limit length (keep extension)
max_length = 255
if len(filename) > max_length:
name_part = filename.rsplit('.', 1)[0]
ext_part = filename.rsplit('.', 1)[1] if '.' in filename else ''
name_part = name_part[:max_length - len(ext_part) - 1]
filename = f"{name_part}.{ext_part}" if ext_part else name_part
return filename
def validate_video_file_extension(filename: str) -> bool:
"""
Validate that filename has an allowed video extension.
Args:
filename: Filename to check
Returns:
True if extension is allowed, False otherwise
"""
allowed_extensions = ['.mp4', '.mov', '.avi', '.mkv']
return any(filename.lower().endswith(ext) for ext in allowed_extensions)
def validate_file_size(file_size: int, max_size: int) -> bool:
"""
Validate that file size is within limits.
Args:
file_size: File size in bytes
max_size: Maximum allowed size in bytes
Returns:
True if size is acceptable, False otherwise
"""
return 0 < file_size <= max_size