Fail closed when the proxy/redirect path decode cap is exceeded (#26050)

The decode-until-stable loops in _sanitize_proxy_path (terminals.py, cap 8) and
_safe_static_redirect_path (models.py, cap 2) proceed with whatever remains after the
cap instead of rejecting it. A path encoded more times than the cap therefore exits the
loop still percent-encoded, passes the literal '..' / prefix checks (the dots are still
%2E, not '..'), and is forwarded to the upstream terminal server, or emitted as a
redirect Location, which then decodes it once more and resolves the traversal. This is
the residual of the decode-until-stable hardening added for CVE-2026-54017: the cap is a
fixed depth, not a true stability guarantee.

Reject when the value is still not stable after the cap (unquote(x) != x), so anything
encoded more deeply than the cap fails closed rather than being forwarded. Legitimate
paths stabilize within a pass or two and are unaffected.

Co-authored-by: DavidCarliez <271374756+DavidCarliez@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Classic298
2026-06-16 22:44:11 +02:00
committed by GitHub
co-authored by DavidCarliez Claude Opus 4.8
parent 3266a8c9eb
commit 05098d25a5
2 changed files with 6 additions and 0 deletions
+3
View File
@@ -60,6 +60,9 @@ def _safe_static_redirect_path(url: str) -> str | None:
if decoded == path:
break
path = decoded
# Fail closed: a value still encoded after the cap would be decoded further downstream.
if unquote(path) != path:
return None
if '\x00' in path or '\\' in path:
return None
if not path.startswith('/'):
+3
View File
@@ -43,6 +43,9 @@ def _sanitize_proxy_path(path: str) -> str | None:
if once == decoded:
break
decoded = once
# Fail closed: still encoded after the cap means the upstream would decode further into traversal.
if unquote(decoded) != decoded:
return None
had_trailing_slash = decoded.endswith('/')
normalized = posixpath.normpath(decoded)
# Remove any leading slashes that would reset the base