Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/5319.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a bug where server-side redirects (``HTTPFound`` and other ``HTTPMove`` subclasses) re-encoded percent-encoded characters (e.g. ``%3F`` for ``?``) in the ``Location`` header, which could break the redirected webserver when the URL contained a query string argument that was itself a URL. The ``Location`` header now preserves the original location string (CR/LF stripped for header-injection safety) while the ``location`` property still returns the parsed ``URL``.
11 changes: 8 additions & 3 deletions aiohttp/web_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,17 @@ def __init__(
super().__init__(
headers=headers, reason=reason, text=text, content_type=content_type
)
self._location = URL(location)
self.headers["Location"] = str(self.location)
self._parsed_location = URL(location)
# Preserve the original location string for the Location header so that
# percent-encoded characters (e.g. "%3F" for "?") are not re-encoded by
# yarl.URL (which decodes them and can break the redirected webserver).
# Only strip CR/LF to prevent request-smuggling-style header injection;
# the URL is still validated via URL(location) above.
self.headers["Location"] = str(location).replace("\r", "").replace("\n", "")

@property
def location(self) -> URL:
return self._location
return self._parsed_location


class HTTPMultipleChoices(HTTPMove):
Expand Down
Loading