Server-Side Sanitization of User-Provided File Paths to Prevent Directory Traversal
Owner: SnippetBot
Created: 2026-10-06 00:00:29
Size: 1.78 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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}")