CVE-2026-46338
PyMdown `snippets` path traversal allows reading files from sibling paths.
- CVSS 4.3
- CWE-22
- Input Validation and Sanitization
- Remote
PyMdown Extensions is a set of extensions for the Python-Markdown markdown project. From 10.0.1 until 10.21.3, pymdownx.snippets uses a string-prefix containment check in SnippetPreprocessor.get_snippet_path() in pymdownx/snippets.py when `restrict_base_path: True`, allowing markdown snippet directives to read files from sibling paths that share the same base_path prefix, such as docs and docs_internal. This is a regression of CVE-2023-32309. This issue is fixed in version 10.21.3.
- CWE
- CWE-22
- CVSS base score
- 4.3
- Published
- 2026-07-16
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Check
- Category
- Input Validation and Sanitization
- Subcategory
- Path Traversal
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- PyMdown Exte
- Fixed by upgrading
- Yes
Solution
Upgrade PyMdown Extensions to version 10.21.3 or later.
Vulnerable code sample
import os
def get_snippet_path(base_path, file_path, current_file_dir):
"""
A representation of the vulnerable function logic before the fix.
`restrict_base_path` is assumed to be True.
"""
# Resolve the user-provided path to an absolute path.
# In the real library, this is resolved relative to the current markdown file.
resolved_path = os.path.abspath(os.path.join(current_file_dir, file_path))
# THE VULNERABLE CHECK:
# A simple string prefix check is used for path containment.
# This check is insufficient. For example, if `base_path` is '/app/docs',
# a `resolved_path` of '/app/docs_internal/secret.txt' will pass
# because the string starts with the `base_path` string.
if not resolved_path.startswith(base_path):
raise ValueError("Path is outside the restricted base path.")
# If the check passes (even incorrectly), the path is returned.
return resolved_pathPatched code sample
import os
def get_snippet_path_fixed(path: str, base_path: str) -> str:
"""
Safely resolves a snippet path, ensuring it is contained within the base_path.
This demonstrates the fix for the path traversal vulnerability.
"""
# Normalize the base path to an absolute path for reliable comparison.
abs_base_path = os.path.abspath(os.path.normpath(base_path))
# Resolve the requested snippet path relative to the base path.
requested_path = os.path.abspath(os.path.normpath(os.path.join(abs_base_path, path)))
# The vulnerable approach used a simple string prefix check, e.g.,
# `requested_path.startswith(abs_base_path)`, which allowed traversal
# to sibling directories like 'docs' and 'docs_internal'.
# The fix uses `os.path.commonpath` to ensure the requested path is
# truly inside the base directory. If the common path of the two is not
# the base path itself, the request is considered invalid.
if os.path.commonpath([abs_base_path, requested_path]) != abs_base_path:
# If the path is outside the restricted base, fall back to the base path.
return abs_base_path
return requested_pathPayload
--(8<-- "docs_internal/secrets.txt"
Cite this entry
@misc{vaitp:cve202646338,
title = {{PyMdown `snippets` path traversal allows reading files from sibling paths.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-46338},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-46338/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
