Source code for seamm_webui.paths

# -*- coding: utf-8 -*-

"""Keeping a path that comes from a request inside the directory it belongs in."""

import os
from pathlib import Path


[docs] def contained(base, name): """The real path of ``name`` under the directory ``base``, or None if it is not in ``base``. Both are resolved with ``os.path.realpath``, which removes ``..`` and follows symbolic links, so a crafted name (``../../etc/passwd``, an absolute path, a link pointing outside) cannot escape. The test is a prefix test of the resolved paths, which static analysis (CodeQL's py/path-injection) recognizes as such a guard; ``Path.is_relative_to``, used before, is as safe but is not recognized, so every use of a checked path was reported. Parameters ---------- base : str or pathlib.Path The directory. name : str or pathlib.Path The path within it, usually from a request; an absolute path is allowed if it lies in ``base``. Returns ------- pathlib.Path or None The resolved path, strictly inside ``base`` (``base`` itself is None). """ root = os.path.realpath(base) target = os.path.realpath(os.path.join(root, name)) # A single prefix test: CodeQL does not follow it through a compound condition if not target.startswith(root + os.sep): return None return Path(target)