Skip to content

Commit

Permalink
Security Enhancement - Added path validation to protect files (#1341)
Browse files Browse the repository at this point in the history
  • Loading branch information
mail4umar authored Dec 3, 2024
1 parent 69953c8 commit ec14e4c
Showing 1 changed file with 89 additions and 2 deletions.
91 changes: 89 additions & 2 deletions verticapy/connection/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def get_connection_file() -> str:
Returns
-------
string
the full path to the
the validated full path to the
auto-connection file.
Examples
Expand Down Expand Up @@ -104,8 +104,95 @@ def get_connection_file() -> str:
if "VERTICAPY_CONNECTION" in os.environ and os.path.exists(
os.environ["VERTICAPY_CONNECTION"]
):
return os.environ["VERTICAPY_CONNECTION"]
path = os.environ["VERTICAPY_CONNECTION"]
validated_path = validate_path(path) # Validate the custom path
return validated_path
# Default to the user's home directory
path = os.path.join(os.path.expanduser("~"), ".vertica")
os.makedirs(path, 0o700, exist_ok=True)
path = os.path.join(path, "connections.verticapy")
return path


def validate_path(path: str):
"""
Validates a file path to ensure it is secure and does not
point to unintended or unsafe locations. This function
prevents users from saving files in restricted system
directories, using symbolic links, or engaging in path
traversal attacks. It also ensures the target directory
is writable and, on Unix-based systems, owned by the current user.
Parameters
----------
path : str
The file path to validate.
Raises
------
ValueError
If the file path violates any of the following rules:
- Points to a restricted system location.
- Uses a symbolic link.
- Includes path traversal sequences (`..`).
- Resides in a directory that is not writable.
- On Unix-based systems, resides in a directory not owned by the current user.
Examples
--------
Validate a safe file path within the user's home directory:
>>> validate_path('/home/user/.vertica/connections.verticapy')
Raise an error for a path in a restricted location:
>>> validate_path('/etc/passwd')
ValueError: Cannot use path '/etc/passwd': it is a restricted system location.
Prevent symbolic links:
>>> validate_path('/home/user/link_to_connections.verticapy')
ValueError: Cannot use path '/home/user/link_to_connections.verticapy': symbolic links are not allowed.
Notes
-----
This function is intended for use in applications where user-specified
file paths are allowed. It helps balance user flexibility with security
by rejecting paths that could lead to vulnerabilities or unauthorized access.
"""
# Restricted locations
restricted_locations = [
"/etc",
"/usr",
"/bin",
"/sbin",
"/var",
"/dev",
"/root",
"C:\\Windows",
"C:\\Program Files",
]
if any(path.startswith(loc) for loc in restricted_locations):
raise ValueError(
f"Cannot use path '{path}': it is a restricted system location."
)

# Ensure directory exists and is writable
directory = os.path.dirname(path)
if not os.path.isdir(directory) or not os.access(directory, os.W_OK):
raise ValueError(f"Cannot use path '{path}': directory is not writable.")

# Prevent symbolic links
if os.path.islink(path):
raise ValueError(f"Cannot use path '{path}': symbolic links are not allowed.")

# Prevent path traversal
if ".." in os.path.normpath(path):
raise ValueError(f"Cannot use path '{path}': path traversal detected.")

# Optional: Restrict to user-owned directories (Linux/Unix)
stat_info = os.stat(directory)
if stat_info.st_uid != os.getuid():
raise ValueError(
f"Cannot use path '{path}': directory is not owned by the current user."
)

0 comments on commit ec14e4c

Please sign in to comment.