Skip to main content

WebOb CVE-2026-44889

MEDIUM
URL Redirection to Untrusted Site (Open Redirect) (CWE-601)
2026-06-04 https://github.com/Pylons/webob GHSA-fh3h-vg37-cc95
6.1
CVSS 3.1
Share

CVSS VectorNVD

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 04, 2026 - 15:21 vuln.today
Analysis Generated
Jun 04, 2026 - 15:21 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 1,869 pypi packages depend on webob (191 direct, 1,691 indirect)

Ecosystem-wide dependent count for version 1.8.10.

DescriptionNVD

Impact

When WebOb normalizes the HTTP Location header to include the request hostname, it does so by parsing the URL that the user is to be redirected to with Python's urllib.parse, and joining it to the base URL. urlsplit (called internally by urljoin) however treats a // at the start of a string as a URI without a scheme, and then treats the next part as the hostname. urljoin will then use that hostname from the second part as the hostname replacing the original one from the request.

In a previous advisory https://github.com/Pylons/webob/security/advisories/GHSA-mg3v-6m49-jhp3 an attempt to fix this was made by forcing the replacement of // with /%2f, however this did not take into account that since Python 3.10 urlsplit internally strips ASCII tab, carriage return, and newline characters from the string, so /\t/attacker.com gets turned into //attacker.com and the attacker is able to bypass the changes introduced in that previous advisory, thereby bringing back the problem that was attempted to be fixed.

>>> parse.urlparse("//attacker.com/some/path")
ParseResult(scheme='', netloc='attacker.com', path='/some/path', params='', query='', fragment='')

WebOb uses urljoin to take the request URI and join the redirect location to it, so assuming the request URI is https://example.org/ and the URL to redirect to is /\t/attacker.com/some/path/:

>>> parse.urljoin("https://example.org/", "/\t/attacker.com/some/path/")
'https://attacker.com/some/path/'

Which redirects from example.org where we want the user to stay to attacker.com.

Patches

This issue has been fixed in WebOb 1.8.10.

Workarounds

Any use of the Response class that includes a location can be rewritten to make sure to always pass a full URI that includes the hostname to redirect the user to, or to validate that the redirect target starts with a scheme (e.g. http:// or https://) before assigning to Response.location.

References

  • https://github.com/Pylons/webob/security/advisories/GHSA-mg3v-6m49-jhp3
  • CVE-2024-42353

Thanks

  • Caleb Brown of Google

AnalysisAI

Open redirect in WebOb (pip/webob <= 1.8.9) enables unauthenticated network attackers to redirect victims to arbitrary attacker-controlled domains by bypassing the prior CVE-2024-42353 patch. The bypass exploits Python 3.10+'s silent stripping of ASCII control characters (tab, CR, LF) from URLs before parsing, so a crafted path like /\t/attacker.com passes the previous // guard, then gets normalized by urlsplit into a protocol-relative URL pointing to attacker.com. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Recon
Attacker identifies WebOb app accepting relative redirect paths
Delivery
Crafts URL embedding tab character before attacker domain (e.g. /\t/attacker.com/phish)
Exploit
Delivers link to victim via phishing or social engineering
Install
Victim clicks link to legitimate application
C2
WebOb _make_location_absolute calls urljoin with crafted path
Execute
Python 3.10 urlsplit strips tab, resolves attacker.com as netloc
Impact
Victim silently redirected to attacker-controlled phishing site

Vulnerability AssessmentAI

Exploitation The target application must be running WebOb version 1.8.9 or earlier on Python 3.10 or higher - the Python version constraint is critical because the tab-stripping behavior in urlsplit that enables the bypass was introduced in Python 3.10. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment CVSS 6.1 Medium (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N) reflects a network-exploitable, low-complexity, unauthenticated vulnerability that requires one instance of user interaction - the victim must follow the crafted redirect - and has changed scope, crossing from the legitimate application domain to an attacker-controlled one. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker crafts a URL such as https://example.org/%09/attacker.com/phishing (where %09 is a URL-encoded tab character) and delivers it to a victim via a phishing email or social engineering. When the victim's browser follows the link, the legitimate WebOb-based application constructs a redirect Response whose Location value is derived from the path, and _make_location_absolute passes /\t/attacker.com through the existing // guard unchallenged. …
Remediation Upgrade WebOb to version 1.8.10, the vendor-released patch documented at https://github.com/Pylons/webob/releases/tag/1.8.10 and implemented across commits 1f681a4f17fc10777ef861e8b43ecb26053bc539 and 2b9fbedafb31180c910cf8526e9ea72b4603d0bc. … Detailed patch versions, workarounds, and compensating controls in full report.

Threat intelligence, references, and detailed analysis are available after sign-in.

Share

CVE-2026-44889 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy