Package: python-webob
Version: 1:1.8.9-2
Severity: normal
Tags: patch  pending

Dear maintainer,

I've prepared an NMU for python-webob (versioned as 1:1.8.10-0.1) and 
uploaded it to DELAYED/2. Please feel free to tell me if I should cancel it.

cu
Adrian
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 +
 debian/patches/0002-Since-Python-3.13-control-characters-are-no-longer-a.patch |   34 -------
 debian/patches/series                                                          |    1 
 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 
 15 files changed, 159 insertions(+), 68 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-02 22:54:18.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	2026-06-24 13:56:11.000000000 +0300
+++ python-webob-1.8.10/debian/changelog	2026-06-28 19:18:17.000000000 +0300
@@ -1,3 +1,12 @@
+python-webob (1:1.8.10-0.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream release.
+    - CVE-2026-44889: Location header normalization during redirect
+      leads to open redirect
+
+ -- Adrian Bunk <[email protected]>  Sun, 28 Jun 2026 19:18:17 +0300
+
 python-webob (1:1.8.9-2) unstable; urgency=medium
 
   * Team upload.
diff -Nru python-webob-1.8.9/debian/patches/0002-Since-Python-3.13-control-characters-are-no-longer-a.patch python-webob-1.8.10/debian/patches/0002-Since-Python-3.13-control-characters-are-no-longer-a.patch
--- python-webob-1.8.9/debian/patches/0002-Since-Python-3.13-control-characters-are-no-longer-a.patch	2026-06-24 13:44:16.000000000 +0300
+++ python-webob-1.8.10/debian/patches/0002-Since-Python-3.13-control-characters-are-no-longer-a.patch	1970-01-01 02:00:00.000000000 +0200
@@ -1,34 +0,0 @@
-From: Delta Regeer <[email protected]>
-Date: Sun, 15 Mar 2026 12:11:56 -0600
-Subject: Since Python 3.13 control characters are no longer allowed in header
- values
-
-This was deprecated in RFC 9112, and thus is disallowed in Python wsgi
-ref.
-
-Origin: upstream, https://github.com/Pylons/webob/commit/7121e8c39dd08efa95aecf0e85d97d1178c152cc.patch
-Bug-Debian: https://bugs.debian.org/1123459
----
- tests/test_client_functional.py | 2 --
- 1 file changed, 2 deletions(-)
-
-diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py
-index 02e0415..2c85196 100644
---- a/tests/test_client_functional.py
-+++ b/tests/test_client_functional.py
-@@ -69,7 +69,6 @@ def cookie_app(req):
-     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 @@ def test_client_cookies(serve, client_app=None):
-         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/debian/patches/series python-webob-1.8.10/debian/patches/series
--- python-webob-1.8.9/debian/patches/series	2026-06-24 13:44:16.000000000 +0300
+++ python-webob-1.8.10/debian/patches/series	2026-06-28 19:18:17.000000000 +0300
@@ -1,3 +1,2 @@
 intersphinx-local.patch
-0002-Since-Python-3.13-control-characters-are-no-longer-a.patch
 0003-Python-3.14-updated-the-DEFAULT_BUFFER_SIZE-to-be-la.patch
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-02 22:55:46.617048000 +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-05-06 09:13:12.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-02 22:54:39.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-05-06 09:46:29.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-02 22:55:46.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-02 22:55:46.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-02 22:55:46.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-05-06 09:52:50.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-05-06 09:46:29.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-05-06 09:46:29.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

Reply via email to