Source code for noxrunner.security.path_sanitizer

"""
Path sanitization for sandbox security.

This module provides path sanitization to prevent path traversal attacks
in sandbox environments.
"""

import os
from pathlib import Path


[docs] class PathSanitizer: """ Sanitizes paths to ensure they're within the sandbox. Security: Prevents path traversal attacks by ensuring all paths are within the sandbox directory. """
[docs] def sanitize(self, path: str, sandbox_path: Path, workspace_name: str = "workspace") -> Path: """ Sanitize a path to ensure it's within the sandbox. Args: path: Path to sanitize (can be absolute or relative) sandbox_path: Base sandbox directory path workspace_name: Name of the workspace directory (default: "workspace") Returns: Sanitized Path object that is guaranteed to be within sandbox Security: - Prevents path traversal attacks (../) - Redirects paths outside sandbox to workspace root - Handles both absolute and relative paths """ sandbox_resolved = sandbox_path.resolve() workspace = sandbox_resolved / workspace_name # Resolve relative paths if os.path.isabs(path): # If absolute, ensure it's within sandbox try: resolved = Path(path).resolve() # Check if resolved path is within sandbox try: resolved.relative_to(sandbox_resolved) # Path is within sandbox, return it return resolved except ValueError: # Path outside sandbox, redirect to workspace return workspace except (OSError, ValueError): return workspace else: # Relative path, check for path traversal first if ".." in path or path.startswith("/"): # Path traversal detected, return workspace root return workspace # Relative path, resolve within workspace try: resolved = (workspace / path).resolve() # Ensure resolved path is still within sandbox try: resolved.relative_to(sandbox_resolved) return resolved except ValueError: # Path traversal detected, return workspace root return workspace except (OSError, ValueError): return workspace
[docs] def ensure_within_sandbox(self, path: Path, sandbox_path: Path) -> bool: """ Check if a path is within the sandbox. Args: path: Path to check sandbox_path: Base sandbox directory path Returns: True if path is within sandbox, False otherwise """ try: path.resolve().relative_to(sandbox_path.resolve()) return True except ValueError: return False
[docs] def sanitize_filename(self, filename: str) -> str: """ Sanitize a filename to prevent path traversal. Args: filename: Filename to sanitize Returns: Sanitized filename (only the basename, no path components) """ # Only use filename, no path traversal return Path(filename).name