Reject a path that escapes a temporary workspace

A workspace check must compare normalized paths, not merely look for .. in supplied text. This example creates a TemporaryDirectory, resolves its root, and then resolves two candidate paths. The first candidate enters reports, returns with .., and ends at report.txt inside the workspace. The second ends at a sibling location and must be rejected.

Path.relative_to() returns the child portion when its receiver is beneath the supplied base; otherwise it raises ValueError. The assertion therefore verifies the accepted candidate’s relative name, while the except branch explicitly records rejection of the escaping candidate. Path.resolve() is important here because it eliminates .. components and follows existing symbolic links before comparison. See the official pathlib documentation and relative_to reference.

This is suitable for a Python 3.6+ baseline, which includes Path.resolve(). It is a path-validation step, not a complete authorization system. In particular, filesystem changes between validation and a later open can create a race, and policies for symlinks, permissions, and platform-specific path rules may need additional handling. The fixture is temporary and its printed result deliberately avoids environment-dependent directory names.

AI-assistance disclosure: this article was drafted with AI assistance and should be reviewed in the context of its application.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as raw_directory:
    workspace = Path(raw_directory).resolve()
    (workspace / "reports").mkdir()

    accepted = (workspace / "reports" / ".." / "report.txt").resolve()
    escaped = (workspace / ".." / "escape.txt").resolve()

    assert accepted.relative_to(workspace) == Path("report.txt")

    try:
        escaped.relative_to(workspace)
    except ValueError:
        print("accepted: report.txt")
        print("rejected: escape.txt")
    else:
        raise AssertionError("escape was accepted")
accepted: report.txt
rejected: escape.txt

Sources

Comments

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic