more path validation
This commit is contained in:
parent
0a3abf439f
commit
c5caa0848b
@ -4,12 +4,42 @@ from src.rendering.renderer import render_page, render_error_page
|
|||||||
from flask import send_file
|
from flask import send_file
|
||||||
from src.rendering.image import generate_thumbnail
|
from src.rendering.image import generate_thumbnail
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class RouteManager:
|
class RouteManager:
|
||||||
def __init__(self, config: Configuration):
|
def __init__(self, config: Configuration):
|
||||||
self.config = config
|
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):
|
def _ensure_route(self, path: str):
|
||||||
"""
|
"""
|
||||||
Escapes the path for anything like
|
Escapes the path for anything like
|
||||||
@ -29,6 +59,9 @@ class RouteManager:
|
|||||||
if part.startswith("__"):
|
if part.startswith("__"):
|
||||||
raise Exception("Illegal path")
|
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):
|
def default_route(self, path: str):
|
||||||
try:
|
try:
|
||||||
self._ensure_route(path)
|
self._ensure_route(path)
|
||||||
@ -38,9 +71,9 @@ class RouteManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return render_error_page(
|
return render_error_page(
|
||||||
403,
|
404,
|
||||||
"Forbidden",
|
"Not Found",
|
||||||
"You do not have permission to access this resource.",
|
"The requested resource was not found on this server.",
|
||||||
self.config.templates_dir,
|
self.config.templates_dir,
|
||||||
)
|
)
|
||||||
file_path: Path = self.config.content_dir / (path if path else "index.md")
|
file_path: Path = self.config.content_dir / (path if path else "index.md")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user