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:
co-authored by
DavidCarliez
Claude Opus 4.8
parent
3266a8c9eb
commit
05098d25a5
@@ -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('/'):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user