import os def sanitize_filename(filename): """ Sanitizes a filename to prevent directory traversal and other malicious paths. Removes path separators and '..'. """ # Remove any directory separators filename = filename.replace('/', '').replace('\\', '') # Remove any .. sequences filename = filename.replace('..', '') # Further restrict characters if needed, e.g., to only alphanumeric, dots, hyphens, underscores # import re # filename = re.sub(r'[^a-zA-Z0-9_.-]', '', filename) return filename def get_safe_filepath(base_dir, user_input_filename): """ Combines a base directory with a sanitized filename to create a safe path. Ensures the resulting path is always within the specified base directory. """ # Resolve base_dir to its real path to prevent symlink tricks base_dir = os.path.realpath(base_dir) # Sanitize the user-provided filename sanitized_name = sanitize_filename(user_input_filename) # Construct the full path full_path = os.path.join(base_dir, sanitized_name) # Ensure the resulting path is still within the base directory # This is a critical double-check after joining resolved_full_path = os.path.realpath(full_path) if not resolved_full_path.startswith(base_dir): raise ValueError("Attempted directory traversal detected!") return resolved_full_path # Example usage: # UPLOAD_DIR = '/var/www/uploads' # user_filename = '../../../etc/passwd.jpg' # try: # safe_path = get_safe_filepath(UPLOAD_DIR, user_filename) # print(f"Safe path: {safe_path}") # except ValueError as e: # print(f"Error: {e}") # user_filename_good = 'my_image.png' # safe_path_good = get_safe_filepath(UPLOAD_DIR, user_filename_good) # print(f"Good path: {safe_path_good}")