Regression in pymdownx.snippets reintroduces sibling-prefix path traversal bypass despite restrict_base_path
Date: 2026-05
Affected: pip/pymdown-extensions
Attack vector: path-traversal
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-46338
CWE: CWE-22
CVSS: 4.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N)

# Summary `pymdownx.snippets` has a regression of the CVE-2023-32309 / GHSA-jh85-wwv9-24hv fix. With `restrict_base_path: True` (the default), the current `filename.startswith(base)` containment check does not enforce a directory boundary. As a result, a markdown snippet directive can read files from sibling paths that share the same prefix as `base_path`, such as `docs` vs `docs_internal`. The regression was introduced in PR #2039 / commit `7c13bda5b7793b172efd1abb6712e156a83fe07d`, which replaced the original directory-identity check with a plain string-prefix comparison. # Details The regression was introduced in commit `7c13bda5b7793b172efd1abb6712e156a83fe07d` (2023-05-15, #2039 *"Fix regression of snippets nested deeply under specified base path"*), which relaxed the original `os.path.samefile(base, os.path.dirname(filename))` check to a plain `startswith(base)`. `SnippetPreprocessor.get_snippet_path()` in `pymdownx/snippets.py`: ```python if self.restrict_base_path: filename = os.path.abspath(os.path.join(base, path)) # If the absolute path is no longer under the specified base path, reject the file if not filename.startswith(base): continue ``` `base` is `os.path.abspath(b)` and has no trailing separator. `str.startswith(base)` is `True` for any `filename` whose string representation begins with the same characters as `base`, regardless of whether those characters end at a directory boundary. Concrete example: * `base = "/x/docs"` * `path


Mitigations:

Architectural layers (MAESTRO):