Skip to content

Commit 63b7835

Browse files
authored
Merge commit from fork
* Fix directory traversal issue with restrict_base_path Found by @gistrec. * Check for os separator as root could already end properly Though paths like root are not advised, we should handle them in a sane manner. * Documentation tests use strict mode which flags numerous false positives Zensical now supports strict mode, but it will flag links as invalid that are not valid due to it not being knowledgeable about common, non-standard syntax.
1 parent 3d18550 commit 63b7835

6 files changed

Lines changed: 38 additions & 3 deletions

File tree

docs/src/markdown/about/changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ icon: lucide/scroll-text
33
---
44
# Changelog
55

6+
## 10.21.3
7+
8+
- **FIX**: Fix regression that allows a snippet to be loaded outside of the base path using directory traversal when
9+
`restrict_base_path` is enabled (the default). Found by @gistrec.
10+
611
## 10.21.2
712

813
- **FIX**: Highlight: Latest Pygments versions cannot handle a "filename" for code block titles of `None`.

pymdownx/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,5 +193,5 @@ def parse_version(ver: str) -> Version:
193193
return Version(major, minor, micro, release, pre, post, dev)
194194

195195

196-
__version_info__ = Version(10, 21, 2, "final")
196+
__version_info__ = Version(10, 21, 3, "final")
197197
__version__ = __version_info__._get_canonical()

pymdownx/snippets.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ def get_snippet_path(self, path):
171171
if self.restrict_base_path:
172172
filename = os.path.abspath(os.path.join(base, path))
173173
# If the absolute path is no longer under the specified base path, reject the file
174-
if not filename.startswith(base):
174+
# Append `os.sep` so a sibling directory whose name shares a prefix
175+
# (e.g. `/x/docs` vs `/x/docs_evil`) cannot satisfy the check.
176+
if not filename.startswith(base + os.sep if not base.endswith(os.sep) else base):
175177
continue
176178
else:
177179
filename = os.path.join(base, path)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ legacy_tox_ini = """
159159
.[extra]
160160
commands=
161161
{envpython} -m pip install .
162-
{envpython} -m zensical build -f zensical.yml --clean --strict
162+
{envpython} -m zensical build -f zensical.yml --clean
163163
{envpython} -m pyspelling -j 8
164164
165165
[testenv:lint]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Snippet

tests/test_extensions/test_snippets.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,20 @@ def test_restricted(self):
730730
True
731731
)
732732

733+
def test_restricted_directory_traversal(self):
734+
"""Test file restriction directory traversal."""
735+
736+
with self.assertRaises(SnippetMissingError):
737+
self.check_markdown(
738+
R'''
739+
--8<-- "../nested_b.txt"
740+
''',
741+
'''
742+
<p>Snippet</p>
743+
''',
744+
True
745+
)
746+
733747

734748
class TestSnippetsMultiNested(util.MdCase):
735749
"""Test multi-nested restriction."""
@@ -786,6 +800,19 @@ def test_restricted(self):
786800
True
787801
)
788802

803+
def test_restricted_directory_traversal(self):
804+
"""Test file restriction directory traversal."""
805+
806+
self.check_markdown(
807+
R'''
808+
--8<-- "../nested_b.txt"
809+
''',
810+
'''
811+
<p>Snippet</p>
812+
''',
813+
True
814+
)
815+
789816

790817
class TestSnippetsAutoAppend(util.MdCase):
791818
"""Test snippet file case."""

0 commit comments

Comments
 (0)