diff --git a/serve.py b/serve.py index e45c56c1..5c7ec7e9 100644 --- a/serve.py +++ b/serve.py @@ -34,15 +34,26 @@ def translate_path(self, path): # HACK: double-slashes are being generated by JS path = path.replace('//', '/') rel_path = path[len('/analysis/docs/'):] - return os.path.join(DOCS_SITE, rel_path) + return self._join_under(DOCS_SITE, rel_path) # Serve /analysis-book/* from BOOK_SITE elif path.startswith('/analysis/'): rel_path = path[len('/analysis/'):] - return os.path.join(BOOK_SITE, rel_path) + return self._join_under(BOOK_SITE, rel_path) # Otherwise, serve nothing (could return a non-existent path) else: raise FileNotFoundError(f"File not found: {path}") + @staticmethod + def _join_under(root, rel_path): + """Join rel_path under root, rejecting path traversal via .. components.""" + candidate = os.path.abspath(os.path.join(root, rel_path)) + try: + if os.path.commonpath([root, candidate]) != root: + return os.path.join(root, '.path-rejected') + except ValueError: + return os.path.join(root, '.path-rejected') + return candidate + if __name__ == '__main__': import argparse