Skip to content

Commit

Permalink
Sanitize static filepaths and prevent path traversal
Browse files Browse the repository at this point in the history
  • Loading branch information
tw4l committed Oct 31, 2024
1 parent 97fffe3 commit de6d8c2
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions pywb/apps/static_handler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import mimetypes
import os
from pathlib import Path

from pathvalidate import sanitize_filepath

from pywb.utils.loaders import LocalFileLoader

from pywb.apps.wbrequestresponse import WbResponse
from pywb.utils.wbexception import NotFoundException


class PathValidationError(Exception):
"""Path validation exception"""


#=================================================================
# Static Content Handler
#=================================================================
Expand All @@ -23,15 +30,29 @@ def __call__(self, environ, url_str):
if url.endswith('/'):
url += 'index.html'

full_path = environ.get('pywb.static_dir')
if full_path:
full_path = os.path.join(full_path, url)
url = sanitize_filepath(url)

canonical_static_path = environ.get('pywb.static_dir')
if not canonical_static_path:
canonical_static_path = self.static_path

full_static_path = os.path.abspath(canonical_static_path)
full_path = None

if environ.get('pywb.static_dir'):
full_path = os.path.join(full_static_path, url)
if not os.path.isfile(full_path):
full_path = None

if not full_path:
full_path = os.path.join(self.static_path, url)

try:
validate_requested_file_path(full_static_path, full_path)
except PathValidationError:
raise NotFoundException('Static File Not Found: ' +
url_str)

try:
data = self.block_loader.load(full_path)

Expand Down Expand Up @@ -65,4 +86,13 @@ def __call__(self, environ, url_str):
raise NotFoundException('Static File Not Found: ' +
url_str)

def validate_requested_file_path(self, static_dir, requested_path):
"""Validate that requested file path is within static dir"""
static_dir = Path(static_dir)
requested_path = Path(requested_path)

if static_dir.resolve() not in requested_path.resolve().parents:
raise PathValidationError("Requested path forbidden")



0 comments on commit de6d8c2

Please sign in to comment.