From 55cfad90a961f4c1d5bdb2d8cba2d6107c52305b Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 31 Dec 2022 08:15:37 -0600 Subject: [PATCH] use werkzeug safe_join to sanitize the requested path no tests changed, so my implementation might have been good, but let's use the provided check --- incorporealcms/pages.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/incorporealcms/pages.py b/incorporealcms/pages.py index 44707d6..0716f4e 100644 --- a/incorporealcms/pages.py +++ b/incorporealcms/pages.py @@ -7,6 +7,7 @@ import re from flask import Blueprint, Markup, abort from flask import current_app as app from flask import redirect, request, send_from_directory +from werkzeug.security import safe_join from incorporealcms.lib import get_meta_str, init_md, render @@ -101,15 +102,16 @@ def request_path_to_instance_resource_path(path): """ # check if the path is allowed base_dir = os.path.realpath(f'{app.instance_path}/pages/') - verbatim_path = os.path.abspath(os.path.join(base_dir, path)) - resolved_path = os.path.realpath(verbatim_path) - logger.debug("base_dir '%s', constructed resolved_path '%s' for path '%s'", base_dir, resolved_path, path) - + safe_path = safe_join(base_dir, path) # bail if the requested real path isn't inside the base directory - if base_dir != os.path.commonpath((base_dir, resolved_path)): + if not safe_path: logger.warning("client tried to request a path '%s' outside of the base_dir!", path) raise PermissionError + verbatim_path = os.path.abspath(safe_path) + resolved_path = os.path.realpath(verbatim_path) + logger.debug("base_dir '%s', constructed resolved_path '%s' for path '%s'", base_dir, resolved_path, path) + # see if we have a real file or if we should infer markdown rendering if os.path.exists(resolved_path): # if this is a file-like request but actually a directory, redirect the user @@ -131,7 +133,7 @@ def request_path_to_instance_resource_path(path): return resolved_path.replace(f'{app.instance_path}{os.path.sep}', ''), 'file' # if we're here, this isn't direct file access, so try markdown inference - verbatim_path = os.path.abspath(os.path.join(base_dir, f'{path}.md')) + verbatim_path = f'{safe_path}.md' resolved_path = os.path.realpath(verbatim_path) # does the final file actually exist?