fix(proxy): decode nested percent-encoded file ids iteratively

An id percent-encoded a thousand or more times sent the recursive decoder past the
interpreter's recursion limit, so a proxy admin key got a 500 instead of a verdict on
the id. The decoder now walks the encodings in a loop, so any depth resolves
This commit is contained in:
mateo-berri 2026-09-10 14:12:53 -07:00
parent 2137ebd643
commit effd233d96
2 changed files with 11 additions and 2 deletions

View file

@ -1,6 +1,7 @@
import posixpath
import re
from collections.abc import Mapping, Sequence
from itertools import accumulate, pairwise, repeat
from types import MappingProxyType
from typing import Any, Final, cast
from urllib.parse import quote, unquote
@ -21,8 +22,8 @@ _MAPPING_PROXY_TYPE: Final[type] = type(MappingProxyType({}))
def _fully_unquoted(value: str) -> str:
decoded: Final = unquote(value)
return value if decoded == value else _fully_unquoted(decoded)
decodings: Final = accumulate(repeat(value), lambda current, _: unquote(current))
return next(current for current, following in pairwise(decodings) if current == following)
def is_managed_cloud_storage_uri(file_id: str) -> bool:

View file

@ -28,3 +28,11 @@ def test_is_managed_cloud_storage_uri_ignores_provider_and_unified_ids():
)
def test_is_managed_cloud_storage_uri_sees_through_percent_encoding(file_id: str):
assert is_managed_cloud_storage_uri(file_id)
def test_is_managed_cloud_storage_uri_survives_an_id_encoded_thousands_of_times():
nested_gs_id = "gs" + "%" + "25" * 5000 + "3A//bucket/x"
nested_plain_id = "%" + "25" * 5000
assert is_managed_cloud_storage_uri(nested_gs_id)
assert not is_managed_cloud_storage_uri(nested_plain_id)