diff --git a/src/routes/routes.py b/src/routes/routes.py index e506e4d..db96295 100644 --- a/src/routes/routes.py +++ b/src/routes/routes.py @@ -4,12 +4,42 @@ from src.rendering.renderer import render_page, render_error_page from flask import send_file from src.rendering.image import generate_thumbnail from functools import lru_cache +import os class RouteManager: def __init__(self, config: Configuration): self.config = config + + def _validate_and_sanitize_path(self, base_dir, requested_path): + """ + Validate and sanitize the requested path to ensure it does not traverse above the base directory. + + :param base_dir: The base directory that the requested path should be within. + :param requested_path: The requested file path to validate. + :return: A secure version of the requested path if valid, otherwise None. + """ + # Normalize both paths + base_dir = os.path.abspath(base_dir) + requested_path = os.path.abspath(requested_path) + + # Check if the requested path is within the base directory + if not requested_path.startswith(base_dir): + return None + + # Ensure the path does not contain any '..' or '.' components + secure_path = os.path.relpath(requested_path, base_dir) + secure_path_parts = secure_path.split(os.sep) + + for part in secure_path_parts: + if part == '.' or part == '..': + return None + + # Reconstruct the secure path + secure_path = os.path.join(base_dir, *secure_path_parts) + return secure_path + def _ensure_route(self, path: str): """ Escapes the path for anything like @@ -28,6 +58,9 @@ class RouteManager: for part in file_path.parts: if part.startswith("__"): raise Exception("Illegal path") + + if not self._validate_and_sanitize_path(self.config.content_dir, str(file_path)): + raise Exception("Illegal path") def default_route(self, path: str): try: @@ -38,9 +71,9 @@ class RouteManager: except Exception as e: print(e) return render_error_page( - 403, - "Forbidden", - "You do not have permission to access this resource.", + 404, + "Not Found", + "The requested resource was not found on this server.", self.config.templates_dir, ) file_path: Path = self.config.content_dir / (path if path else "index.md")