From c85d669de387b40e667fd6942c6cc1c15b4f5964 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Mon, 7 Mar 2022 11:26:08 -0800 Subject: [PATCH] Fix bug with percentage redirects, close #1650 --- datasette/utils/__init__.py | 7 ++++++- tests/test_html.py | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index 79feeef6..e7c9fb1c 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -10,6 +10,7 @@ import markupsafe import mergedeep import os import re +import secrets import shlex import tempfile import typing @@ -1172,4 +1173,8 @@ def dash_encode(s: str) -> str: @documented def dash_decode(s: str) -> str: "Decodes a dash-encoded string, so ``-2Ffoo-2Fbar`` -> ``/foo/bar``" - return urllib.parse.unquote(s.replace("-", "%")) + # Avoid accidentally decoding a %2f style sequence + temp = secrets.token_hex(16) + s = s.replace("%", temp) + decoded = urllib.parse.unquote(s.replace("-", "%")) + return decoded.replace(temp, "%") diff --git a/tests/test_html.py b/tests/test_html.py index de703284..55d78c05 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -961,6 +961,10 @@ def test_no_alternate_url_json(app_client, path): "/fivethirtyeight/twitter-ratio%2Fsenators", "/fivethirtyeight/twitter-2Dratio-2Fsenators", ), + ( + "/fixtures/table%2Fwith%2Fslashes", + "/fixtures/table-2Fwith-2Fslashes", + ), # query string should be preserved ("/foo/bar%2Fbaz?id=5", "/foo/bar-2Fbaz?id=5"), ),