Update dependency WebOb to v1.8.11 [SECURITY] - #69
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
==1.8.10→==1.8.11WebOb: Open redirect in Location header normalization via leading C0 control / space characters
CVE-2026-54770 / GHSA-6hx8-3wjj-gr8g
More information
Details
Summary
This is a third follow-up to CVE-2024-42353 / GHSA-mg3v-6m49-jhp3
and CVE-2026-44889 / GHSA-fh3h-vg37-cc95.
WebOb makes the
Locationheader absolute when it serves a redirect. To stop arelative or protocol-relative target from redirecting users off-host, it checks
the value for a URI scheme and for a leading
//, then joins it against therequest URI with
urllib.parse.urljoin(). The previous fix additionally strippedASCII tab/CR/LF from the value before those checks.
However, on Python 3.10+
urllib.parse.urljoin()(viaurlsplit()) does morethan remove tab/CR/LF: it also strips leading and trailing C0 control
characters (
U+0000–U+001F) and spaces from the URL before parsing it.Because WebOb's guard checks (
SCHEME_REandstartswith("//")) run against theun-stripped value, a single leading space or control byte slips past them, and
urljoin()then silently removes that byte and parses what remains as aprotocol-relative — or even absolute — URL. The result is an open redirect to an
attacker-controlled host.
Details
Response._make_location_absolute()(insrc/webob/response.py) performed,prior to the fix:
Consider the Location value
" //www.example.com/test"(a single leading space):\t,\r,\n— the leading spacesurvives.
SCHEME_RE(^[a-z]+:) does not match — the value starts with a space.value.startswith("//")is False — the value starts with a space, not/. The//→/%2fneutralization is skipped.urllib.parse.urljoin(_request_uri(environ), " //www.example.com/test")thenstrips the leading space before parsing, sees
//www.example.com/test,treats it as protocol-relative, and returns
http://www.example.com/test.The same bypass works with a value such as
" https://www.example.com/test"(leading space + a full scheme):
SCHEME_REdoes not match the space-prefixedstring, but
urljoin()strips the space and returns the fully absoluteattacker URL
https://www.example.com/test.Any C0 control character works equally well in place of the space, e.g.
"\x00//www.example.com/test"or"\x1f//www.example.com/test", becauseurlsplit()strips the whole leading C0-control-and-space run.Affected entry points
Response.location— any application that sets a relative/attacker-influencedLocationand serves the response (the classic redirect path).Request.relative_url()— usedurllib.parse.urljoin()directly and wassubject to the same character stripping.
webob.exc._HTTPMovesubclasses (HTTPMovedPermanently,HTTPFound,HTTPSeeOther,HTTPTemporaryRedirect,HTTPPermanentRedirect, etc.) — thesebuilt their absolute Location with
urlparse.urljoin(req.path_url, self.location)without going through
_make_location_absolute()at all, so they bypassedeven the tab/CR/LF strip and the
//→/%2fneutralization. A protocol-relativelocation passed to e.g.
HTTPFound(location="//evil.example")redirected off-host.Proof of Concept
Absolute-URL variant:
Via the HTTP exceptions:
Impact
An unauthenticated remote attacker who controls (in whole or part) the redirect
target of an application built on WebOb can redirect a user from a trusted host to
an attacker-controlled host. This enables phishing and credential-theft campaigns
that abuse the trusted origin, and can be chained with OAuth/SSO
redirect_uriflows to leak tokens. Exploitation requires user interaction (following the
redirect). Confidentiality and integrity impact are limited (
L); the scope ischanged (
C) because the trust boundary of the originating site is crossed.Patches
Fixed by replacing the use of
urllib.parse.urljoin()with WebOb's ownRFC 3986 reference-resolution implementation,
webob.util.urljoin(), whichresolves the reference exactly as given, character for character, with no
whitespace or control-character removal.
Response._make_location_absolute()now useswebob.util.urljoin().Request.relative_url()now useswebob.util.urljoin().webob.exc._HTTPMovenow normalizes its Location through the same_make_location_absolute()code path asResponse, so protocol-relative andwhitespace-smuggled locations are neutralized there too.
Users should upgrade to the patched release. There are no API changes.
Workarounds
Locationheader / redirect target to a fully-qualified URIwhose host you control, or strictly allowlist redirect destinations before
handing them to WebOb.
https://yourhost/(or avalidated relative path with no leading whitespace/control bytes).
References
urllib.parseURL stripping behavior (CPython 3.10+, removal of leadingand trailing C0 control and space characters): https://docs.python.org/3/library/urllib.parse.html
To report a vulnerability to the Pylons Project please take a look at:
https://github.com/Pylons/.github/blob/main/SECURITY.md
pylons-project-security@googlegroups.com(the Pylons Project requests a 90-day disclosure embargo)
Credit
Reported via the Pylons Project security mailing list by:
Response._make_location_absolute(): the 1.8.10 fix stripped only ASCIItab/CR/LF, but
urllib.parse.urljoin()also strips leading C0 control andspace characters, so values such as
" //attacker.example/path"(and" https://attacker.example/path") still escaped off-host.webob.exc._HTTPMoveredirect exceptions (
HTTPFoundand friends) performed their ownurllib.parse.urljoin()normalization and never went through_make_location_absolute(), so a protocol-relative location such as//evil.example/path/redirected off-host through that separate code path.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.