Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected], [email protected]
Control: affects -1 + src:python-webob
User: [email protected]
Usertags: pu
* New upstream release.
- CVE-2026-44889: Location header normalization during redirect
leads to open redirect
The only change in the new upstream release that is not the CVE fix
and its tests is an unrelated test fix in test_client_functional.py.
diffstat for python-webob-1.8.9 python-webob-1.8.10
.gitignore | 20 -----------------
.readthedocs.yaml | 14 ++++++++++++
CHANGES.txt | 15 +++++++++++++
PKG-INFO | 33 ++++++++++++++++++++++++++--
debian/changelog | 9 +++++++
setup.py | 3 +-
src/WebOb.egg-info/PKG-INFO | 33 ++++++++++++++++++++++++++--
src/WebOb.egg-info/SOURCES.txt | 2 -
src/WebOb.egg-info/requires.txt | 1
src/webob/response.py | 11 ++++++---
tests/test_client_functional.py | 2 -
tests/test_response.py | 46 ++++++++++++++++++++++++++++++++++++++++
tox.ini | 3 --
13 files changed, 159 insertions(+), 33 deletions(-)
diff -Nru python-webob-1.8.9/CHANGES.txt python-webob-1.8.10/CHANGES.txt
--- python-webob-1.8.9/CHANGES.txt 2024-10-24 06:10:29.000000000 +0300
+++ python-webob-1.8.10/CHANGES.txt 2026-06-29 08:24:25.000000000 +0300
@@ -1,3 +1,18 @@
+1.8.10 (2026-06-02)
+-------------------
+
+Security Fix
+~~~~~~~~~~~~
+
+- The fix for CVE-2024-42353 was incomplete: a Location value containing
+ ASCII tab, carriage return, or line feed characters between consecutive
+ slashes could still be interpreted as a protocol-relative URL by
+ ``urllib.parse.urljoin`` on Python 3.10+, allowing an open redirect.
+
+ See https://github.com/Pylons/webob/security/advisories/GHSA-fh3h-vg37-cc95
+
+ Thanks to Caleb Brown of Google for the report.
+
1.8.9 (2024-11-23)
------------------
diff -Nru python-webob-1.8.9/debian/changelog
python-webob-1.8.10/debian/changelog
--- python-webob-1.8.9/debian/changelog 2025-01-12 19:39:16.000000000 +0200
+++ python-webob-1.8.10/debian/changelog 2026-07-03 20:13:14.000000000
+0300
@@ -1,3 +1,12 @@
+python-webob (1:1.8.10-0+deb13u1) trixie; urgency=medium
+
+ * Non-maintainer upload.
+ * New upstream release.
+ - CVE-2026-44889: Location header normalization during redirect
+ leads to open redirect
+
+ -- Adrian Bunk <[email protected]> Fri, 03 Jul 2026 20:13:14 +0300
+
python-webob (1:1.8.9-1) unstable; urgency=medium
* Team upload.
diff -Nru python-webob-1.8.9/.gitignore python-webob-1.8.10/.gitignore
--- python-webob-1.8.9/.gitignore 2018-04-05 05:06:35.000000000 +0300
+++ python-webob-1.8.10/.gitignore 1970-01-01 02:00:00.000000000 +0200
@@ -1,20 +0,0 @@
-*$py.class
-*.egg
-*.pyc
-*.pyo
-*.swp
-*~
-.*.swp
-.tox/
-__pycache__/
-_build/
-build/
-dist/
-env*/
-.coverage
-.coverage.*
-.cache/
-WebOb.egg-info/
-pytest*.xml
-coverage*.xml
-.pytest_cache/
diff -Nru python-webob-1.8.9/PKG-INFO python-webob-1.8.10/PKG-INFO
--- python-webob-1.8.9/PKG-INFO 2024-10-24 06:17:49.027817500 +0300
+++ python-webob-1.8.10/PKG-INFO 2026-06-29 08:24:25.000000000 +0300
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
Name: WebOb
-Version: 1.8.9
+Version: 1.8.10
Summary: WSGI request and response object
Home-page: http://webob.org/
Author: Ian Bicking
@@ -32,6 +32,20 @@
Provides-Extra: docs
Requires-Dist: Sphinx>=1.7.5; extra == "docs"
Requires-Dist: pylons-sphinx-themes; extra == "docs"
+Requires-Dist: setuptools; extra == "docs"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: keywords
+Dynamic: license
+Dynamic: license-file
+Dynamic: maintainer
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
WebOb
=====
@@ -70,6 +84,21 @@
WebOb was authored by Ian Bicking and is currently maintained by the `Pylons
Project <https://pylonsproject.org/>`_ and a team of contributors.
+1.8.10 (2026-06-02)
+-------------------
+
+Security Fix
+~~~~~~~~~~~~
+
+- The fix for CVE-2024-42353 was incomplete: a Location value containing
+ ASCII tab, carriage return, or line feed characters between consecutive
+ slashes could still be interpreted as a protocol-relative URL by
+ ``urllib.parse.urljoin`` on Python 3.10+, allowing an open redirect.
+
+ See https://github.com/Pylons/webob/security/advisories/GHSA-fh3h-vg37-cc95
+
+ Thanks to Caleb Brown of Google for the report.
+
1.8.9 (2024-11-23)
------------------
diff -Nru python-webob-1.8.9/.readthedocs.yaml
python-webob-1.8.10/.readthedocs.yaml
--- python-webob-1.8.9/.readthedocs.yaml 1970-01-01 02:00:00.000000000
+0200
+++ python-webob-1.8.10/.readthedocs.yaml 2026-06-29 08:24:25.000000000
+0300
@@ -0,0 +1,14 @@
+# https://docs.readthedocs.io/en/stable/config-file/v2.html
+version: 2
+build:
+ os: ubuntu-22.04
+ tools:
+ python: '3.12'
+sphinx:
+ configuration: docs/conf.py
+python:
+ install:
+ - method: pip
+ path: .
+ extra_requirements:
+ - docs
diff -Nru python-webob-1.8.9/setup.py python-webob-1.8.10/setup.py
--- python-webob-1.8.9/setup.py 2024-10-24 06:17:01.000000000 +0300
+++ python-webob-1.8.10/setup.py 2026-06-29 08:24:25.000000000 +0300
@@ -21,11 +21,12 @@
docs_extras = [
'Sphinx >= 1.7.5',
'pylons-sphinx-themes',
+ 'setuptools'
]
setup(
name='WebOb',
- version='1.8.9',
+ version='1.8.10',
description="WSGI request and response object",
long_description=README + '\n\n' + CHANGES,
classifiers=[
diff -Nru python-webob-1.8.9/src/webob/response.py
python-webob-1.8.10/src/webob/response.py
--- python-webob-1.8.9/src/webob/response.py 2024-08-14 08:06:46.000000000
+0300
+++ python-webob-1.8.10/src/webob/response.py 2026-06-29 08:24:25.000000000
+0300
@@ -1281,12 +1281,17 @@
@staticmethod
def _make_location_absolute(environ, value):
+ # urllib.parse.urlsplit() (called internally by urljoin) strips
+ # ASCII tab, CR, and LF from the URL on Python 3.10+. Strip them
+ # ourselves first so they cannot be used to bypass the SCHEME_RE
+ # or protocol-relative ("//") checks below. See CVE-2024-42353,
+ #
https://github.com/Pylons/webob/security/advisories/GHSA-mg3v-6m49-jhp3,
+ # and the follow-up advisory GHSA-fh3h-vg37-cc95.
+ value = value.replace("\t", "").replace("\r", "").replace("\n", "")
+
if SCHEME_RE.search(value):
return value
- # This is to fix an open redirect issue due to the way that
- # urlparse.urljoin works. See CVE-2024-42353 and
- #
https://github.com/Pylons/webob/security/advisories/GHSA-mg3v-6m49-jhp3
if value.startswith("//"):
value = "/%2f{}".format(value[2:])
new_location = urlparse.urljoin(_request_uri(environ), value)
diff -Nru python-webob-1.8.9/src/WebOb.egg-info/PKG-INFO
python-webob-1.8.10/src/WebOb.egg-info/PKG-INFO
--- python-webob-1.8.9/src/WebOb.egg-info/PKG-INFO 2024-10-24
06:17:48.000000000 +0300
+++ python-webob-1.8.10/src/WebOb.egg-info/PKG-INFO 2026-06-29
08:24:25.000000000 +0300
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
Name: WebOb
-Version: 1.8.9
+Version: 1.8.10
Summary: WSGI request and response object
Home-page: http://webob.org/
Author: Ian Bicking
@@ -32,6 +32,20 @@
Provides-Extra: docs
Requires-Dist: Sphinx>=1.7.5; extra == "docs"
Requires-Dist: pylons-sphinx-themes; extra == "docs"
+Requires-Dist: setuptools; extra == "docs"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: keywords
+Dynamic: license
+Dynamic: license-file
+Dynamic: maintainer
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
WebOb
=====
@@ -70,6 +84,21 @@
WebOb was authored by Ian Bicking and is currently maintained by the `Pylons
Project <https://pylonsproject.org/>`_ and a team of contributors.
+1.8.10 (2026-06-02)
+-------------------
+
+Security Fix
+~~~~~~~~~~~~
+
+- The fix for CVE-2024-42353 was incomplete: a Location value containing
+ ASCII tab, carriage return, or line feed characters between consecutive
+ slashes could still be interpreted as a protocol-relative URL by
+ ``urllib.parse.urljoin`` on Python 3.10+, allowing an open redirect.
+
+ See https://github.com/Pylons/webob/security/advisories/GHSA-fh3h-vg37-cc95
+
+ Thanks to Caleb Brown of Google for the report.
+
1.8.9 (2024-11-23)
------------------
diff -Nru python-webob-1.8.9/src/WebOb.egg-info/requires.txt
python-webob-1.8.10/src/WebOb.egg-info/requires.txt
--- python-webob-1.8.9/src/WebOb.egg-info/requires.txt 2024-10-24
06:17:48.000000000 +0300
+++ python-webob-1.8.10/src/WebOb.egg-info/requires.txt 2026-06-29
08:24:25.000000000 +0300
@@ -5,6 +5,7 @@
[docs]
Sphinx>=1.7.5
pylons-sphinx-themes
+setuptools
[testing]
pytest>=3.1.0
diff -Nru python-webob-1.8.9/src/WebOb.egg-info/SOURCES.txt
python-webob-1.8.10/src/WebOb.egg-info/SOURCES.txt
--- python-webob-1.8.9/src/WebOb.egg-info/SOURCES.txt 2024-10-24
06:17:49.000000000 +0300
+++ python-webob-1.8.10/src/WebOb.egg-info/SOURCES.txt 2026-06-29
08:24:25.000000000 +0300
@@ -1,5 +1,5 @@
.coveragerc
-.gitignore
+.readthedocs.yaml
CHANGES.txt
HISTORY.txt
MANIFEST.in
diff -Nru python-webob-1.8.9/tests/test_client_functional.py
python-webob-1.8.10/tests/test_client_functional.py
--- python-webob-1.8.9/tests/test_client_functional.py 2024-08-14
08:06:43.000000000 +0300
+++ python-webob-1.8.10/tests/test_client_functional.py 2026-06-29
08:24:25.000000000 +0300
@@ -69,7 +69,6 @@
resp = Response('test')
resp.headers.add('Set-Cookie', 'a=b')
resp.headers.add('Set-Cookie', 'c=d')
- resp.headerlist.append(('X-Crazy', 'value\r\n continuation'))
return resp
@@ -79,7 +78,6 @@
req = Request.blank(server.url + '/?test')
resp = req.send(client_app)
assert resp.headers.getall('Set-Cookie') == ['a=b', 'c=d']
- assert resp.headers['X-Crazy'] == 'value, continuation',
repr(resp.headers['X-Crazy'])
@wsgify
diff -Nru python-webob-1.8.9/tests/test_response.py
python-webob-1.8.10/tests/test_response.py
--- python-webob-1.8.9/tests/test_response.py 2024-08-14 08:06:46.000000000
+0300
+++ python-webob-1.8.10/tests/test_response.py 2026-06-29 08:24:25.000000000
+0300
@@ -1042,6 +1042,52 @@
assert req.get_response(res).location ==
"http://localhost/%2fwww.example.com/test"
[email protected]("payload", [
+ "/\t/www.example.com/test",
+ "\t//www.example.com/test",
+ "//\twww.example.com/test",
+ "/\t\t/www.example.com/test",
+])
+def test_location_no_open_redirect_tab_bypass(payload):
+ # Follow-up to CVE-2024-42353. urllib.parse.urlsplit() (used internally
+ # by urljoin) strips ASCII tab on Python 3.10+, which allowed a
+ # Location value to bypass the "//" check and be parsed as
+ # protocol-relative. See GHSA-fh3h-vg37-cc95. (CR and LF are already
+ # rejected by the location header setter, so only tab is reachable
+ # via the public API.)
+ res = Response()
+ res.status = "301"
+ res.location = payload
+ req = Request.blank("/")
+ assert req.get_response(res).location == (
+ "http://localhost/%2fwww.example.com/test"
+ )
+
+
[email protected]("payload", [
+ "/\t/www.example.com/test",
+ "/\n/www.example.com/test",
+ "/\r/www.example.com/test",
+ "\t//www.example.com/test",
+ "\n//www.example.com/test",
+ "\r//www.example.com/test",
+ "//\twww.example.com/test",
+ "//\nwww.example.com/test",
+ "//\rwww.example.com/test",
+ "//\tw\nww.example.com/test",
+])
+def test__make_location_absolute_strips_url_whitespace(payload):
+ # Defense in depth for GHSA-fh3h-vg37-cc95: even when called with a
+ # Location value that bypasses the descriptor's CR/LF check (e.g. via
+ # direct manipulation of _headerlist), tab/CR/LF must not be usable to
+ # turn a relative path into a protocol-relative redirect.
+ result = Response._make_location_absolute(
+ {"wsgi.url_scheme": "http", "HTTP_HOST": "example.com:80"},
+ payload,
+ )
+ assert result == "http://example.com/%2fwww.example.com/test"
+
+
@pytest.mark.xfail(sys.version_info < (3,0),
reason="Python 2.x unicode != str, WSGI requires str. Test "
"added due to https://github.com/Pylons/webob/issues/247. "
diff -Nru python-webob-1.8.9/tox.ini python-webob-1.8.10/tox.ini
--- python-webob-1.8.9/tox.ini 2024-10-24 06:11:34.000000000 +0300
+++ python-webob-1.8.10/tox.ini 2026-06-29 08:24:25.000000000 +0300
@@ -1,7 +1,7 @@
[tox]
requires = virtualenv<20.22.0
envlist =
- py27,py34,py35,py36,py37,py313,pypy,
+ py27,py34,py35,py36,py37,pypy,
docs,coverage,pep8
skip_missing_interpreters = True
@@ -14,7 +14,6 @@
py35: python3.5
py36: python3.6
py37: python3.7
- py313: python3.13
pypy: pypy
py2: python2.7
py3: python3.5