From a8c538a3958871fbd99f04c1940b12e786e738e2 Mon Sep 17 00:00:00 2001 From: Thomas Barregren Date: Tue, 2 Jun 2026 22:25:31 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20.md=20URLs=20with=20non-ASCII=20slugs=20?= =?UTF-8?q?(=C3=A5/=C3=A4/=C3=B6)=20never=20resolve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RewriteHandler read the request path through sanitize_text_field(), which deliberately strips every percent-encoded octet (%[a-f0-9]{2}). Non-ASCII URL characters are percent-encoded octets (å=%c3%a5, ä=%c3%a4, ö=%c3%b6), so they were silently deleted, mangling the slug so url_to_postid() could never match and no Markdown was served. Use esc_url_raw() instead, which preserves valid percent-encoding, in both parse_markdown_url() and handle_markdown_request() (the latter builds the /.md/ -> /.md trailing-slash redirect). ASCII slugs are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Router/RewriteHandler.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Router/RewriteHandler.php b/src/Router/RewriteHandler.php index e7220a1..9a93a55 100644 --- a/src/Router/RewriteHandler.php +++ b/src/Router/RewriteHandler.php @@ -97,7 +97,11 @@ public function prevent_markdown_redirect($redirect_url, $requested_url) { * @return void */ public function parse_markdown_url(\WP $wp): void { - $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : ''; + // Use esc_url_raw() rather than sanitize_text_field() here: the latter + // strips every percent-encoded octet (%[a-f0-9]{2}), which destroys + // non-ASCII slugs (e.g. å/ä/ö, encoded as %c3%a5/%c3%a4/%c3%b6) and makes + // the post lookup below fail. esc_url_raw() preserves the encoding. + $request_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : ''; $path = wp_parse_url($request_uri, PHP_URL_PATH); if ($path === false || $path === null) { return; @@ -276,7 +280,9 @@ public function handle_markdown_request(): void { return; } - $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : ''; + // esc_url_raw() preserves percent-encoded octets so the trailing-slash + // redirect works for non-ASCII slugs (see parse_markdown_url()). + $request_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : ''; // Enforce lowercase .md extension — reject wrong case and let WordPress 404. if (