Repository navigation
Escape '.' and '..' path segments when normalizing URLs into ZIM paths - #361
Merged
Merged
Conversation
A `.` or `..` path segment is an RFC 3986 dot-segment, resolved away by any URI consumer (including a reader turning a relative link back into an absolute one). When such a segment is folded into a ZIM path, e.g. from a querystring containing a `/../`, it is otherwise misinterpreted as navigation instead of being kept as a literal entry name. Prefix any path segment that is exactly `.` or `..` with a `_`, in both Python and JS URL rewriting, so it stays inert for URI resolution while remaining distinguishable. Look-alikes (`foo..`, `..foo`, `...`) are left untouched since they are not dot-segments. Supersedes #314, fixes #321
benoit74
force-pushed
the
fix-dot-segments-escaping-321
branch
from
October 22, 2026 14:11
050fcf3 to
b6be9a9
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #361 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 42 42
Lines 2852 2855 +3
Branches 428 428
=========================================
+ Hits 2852 2855 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A ZIM path must never contain a literal
.or..path segment: per RFC 3986 these dot-segments are resolved away by any URI consumer (including a reader turning a relative link back into an absolute one). When such a segment is folded into a ZIM path, e.g. from a querystring containing a/../(xtree.html?css=../../prg), it is otherwise misinterpreted as navigation instead of being kept as a literal entry name, pointing the link to the wrong resource.This is the bug reported in #321 (itself extracted from openzim/warc2zim#380). It was first tackled in #314, which fixed the (now already-gone) crash but, per review there, got the semantics wrong: it ignored
../.found in a querystring rather than treating them as the literal path segments they become once folded into the ZIM path. Resolving the correct approach required first settling openzim/overview#90 (should dot-segments be fixed in readers, or forbidden at the ZIM spec level), which landed on forbidding them, and the concrete escaping scheme agreed in #321.Fix
Any path segment that is exactly
.or..is now prefixed with a_when a URL is normalized into a ZIM path, e.g.a/../bbecomesa/_../b. This is applied uniformly to the whole ZIM path (host + path + querystring), so it also covers dot-segments folded in from a querystring. Look-alike segments such asfoo..,..fooor...are not dot-segments and are left untouched.Implemented identically in both the Python (
ArticleUrlRewriter.normalize) and JS (urlRewriteFunction) rewriters, per the earlier review on #314 asking for parity between the two.Tests
ArticleUrlRewriter.escape_dot_segments/ JSescapeDotSegmentsunit tests covering dot-segments, consecutive dot-segments, trailing dot-segments, and look-alikes.TestNormalize/ JSurlRewriteFunctiontests covering the querystring-dot-segment crash case from Rewriter choke on a relative URL inside a querystring #321.test_relative_url_round_tripcase asserting that resolving the rewritten link (as a reader would, including RFC 3986 dot-segment removal) gives back the correct, escaped ZIM path.Full
tests/rewriting/suite passes (570 tests); JSyarn testpasses (153 tests);ruff/pyright/eslint/prettierall clean.Supersedes #314 (same underlying bug, different and now-agreed-upon fix).
Fixes #321