On 9/4/26 12:55 PM, Adam D. Barratt wrote:
Control: tags -1 + confirmed

On Thu, 2026-08-20 at 14:20 +0200, Thomas Goirand wrote:
I'd like to upload a new version of Zaqar to address:
https://security.openstack.org/ossa/OSSA-2026-029.html
aka:
https://bugs.debian.org/1142858

Please go ahead.

Regards,

Adam

Hi Adam,

I integrated this change to the previous ones (re-indented here, so it wraps at 74 cols, for readability):

  * CVE-2026-97404 / OSSA-2026-042: Zaqar empty URL-Signature header
    bypasses authentication. Applied upstream patch "Fix authentication
    bypass by empty URL-Signature". (Closes: #1148897):
    - CVE-2026-97404_OSSA-2026-042_Fix_authe....patch
  * CVE-2026-107363 / OSSA-2026-043: Zaqar WebSocket project
    substitution allows cross-project queue access. Applied upstream
    patch "Prohibit arbitrary project-id for websocket protocol access".
    (Closes: #1150261):
    - CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_....patch

New debdiff is attached. Package has been uploaded. Please approve it.

Cheers,

Thomas Goirand (zigo)
diff -Nru zaqar-20.0.0/debian/changelog zaqar-20.0.0/debian/changelog
--- zaqar-20.0.0/debian/changelog       2025-07-11 14:47:00.000000000 +0200
+++ zaqar-20.0.0/debian/changelog       2026-10-13 14:10:33.000000000 +0200
@@ -1,3 +1,19 @@
+zaqar (20.0.0-2+deb13u1) trixie; urgency=medium
+
+  * CVE-2026-66139 / OSSA-2026-029: EXTRA-SPEC header bypasses Keystone
+    authentication. Applied upstream patch: "Do not bypass authentication for
+    requests with EXTRA-SPEC header". (Closes: #1142858).
+  * CVE-2026-97404 / OSSA-2026-042: Zaqar empty URL-Signature header
+    bypasses authentication. Applied upstream patch "Fix authentication
+    bypass by empty URL-Signature". (Closes: #1148897):
+    - CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_....patch
+  * CVE-2026-107363 / OSSA-2026-043: Zaqar WebSocket project substitution
+    allows cross-project queue access. Applied upstream patch "Prohibit
+    arbitrary project-id for websocket protocol access". (Closes: #1150261):
+    - CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_fo....patch
+
+ -- Thomas Goirand <[email protected]>  Tue, 13 Oct 2026 14:10:33 +0200
+
 zaqar (20.0.0-2) unstable; urgency=medium
 
   * Add export OS_OSLO_MESSAGING_RABBIT__PROCESSNAME to all daemons.
diff -Nru 
zaqar-20.0.0/debian/patches/CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_for_websocket_protocol_access.patch
 
zaqar-20.0.0/debian/patches/CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_for_websocket_protocol_access.patch
--- 
zaqar-20.0.0/debian/patches/CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_for_websocket_protocol_access.patch
 1970-01-01 01:00:00.000000000 +0100
+++ 
zaqar-20.0.0/debian/patches/CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_for_websocket_protocol_access.patch
 2026-10-13 14:10:33.000000000 +0200
@@ -0,0 +1,120 @@
+Description: Prohibit arbitrary project-id for websocket protocol access
+From: Takashi Kajinami <[email protected]>
+Date: Wed, 07 Oct 2026 02:10:12 +0900
+Bug: https://launchpad.net/bugs/2161402
+Bug-Debian: https://bugs.debian.org/1150261
+Change-Id: Id6055f9f6f115249a1321165ae93a91e69ea9dcc
+Signed-off-by: Takashi Kajinami <[email protected]>
+Co-Authored-By: Hao Wang <[email protected]>
+Origin: https://review.opendev.org/c/zaqar/+/1009254
+Last-Update: 2026-10-07
+
+diff --git a/releasenotes/notes/bug-2161402-f0b9d2052c12b958.yaml 
b/releasenotes/notes/bug-2161402-f0b9d2052c12b958.yaml
+new file mode 100644
+index 0000000..e2e8188
+--- /dev/null
++++ b/releasenotes/notes/bug-2161402-f0b9d2052c12b958.yaml
+@@ -0,0 +1,6 @@
++---
++security:
++  - |
++    `Bug 2161402 <https://bugs.launchpad.net/zaqar/+bug/2161402>`_: Fixed
++    websocket protocol support allowing arbitrary cross project access for
++    any authenticated users.
+diff --git a/zaqar/tests/unit/transport/websocket/v2/test_auth.py 
b/zaqar/tests/unit/transport/websocket/v2/test_auth.py
+index beaeb00..ce0b615 100644
+--- a/zaqar/tests/unit/transport/websocket/v2/test_auth.py
++++ b/zaqar/tests/unit/transport/websocket/v2/test_auth.py
+@@ -45,8 +45,12 @@
+         auth_mock = mock.patch.object(auth_token.AuthProtocol, '__call__')
+         self.addCleanup(auth_mock.stop)
+         self.auth = auth_mock.start()
+-        self.env = {'keystone.token_info': {
+-            'token': {'expires_at': '2035-08-05T15:16:33.603700+00:00'}}}
++        self.env = {
++            'keystone.token_info': {
++                'token': {'expires_at': '2035-08-05T15:16:33.603700+00:00'}
++            },
++            'X-PROJECT-ID': self.project_id,
++        }
+ 
+     def test_post(self):
+         headers = self.headers.copy()
+@@ -69,17 +73,41 @@
+         self.assertEqual('200 OK', responses[0])
+ 
+         # Check that the env is available to future requests
+-        req = jsonutils.dumps({'action': consts.MESSAGE_LIST,
+-                               'body': {'queue_name': 'myqueue'},
+-                               'headers': self.headers})
+-        process_request = mock.patch.object(self.protocol._handler,
+-                                            'process_request').start()
++        req = jsonutils.dumps({
++            'action': consts.MESSAGE_LIST,
++            'body': {'queue_name': 'myqueue'},
++            'headers': self.headers
++        })
++        process_request = mock.patch.object(
++            self.protocol._handler, 'process_request').start()
+         process_request.return_value = self.protocol._handler.create_response(
+             200, {})
+         self.protocol.onMessage(req, False)
+         self.assertEqual(1, process_request.call_count)
+         self.assertEqual(self.env, process_request.call_args[0][0]._env)
+ 
++    def test_different_project(self):
++        headers = self.headers.copy()
++        headers['X-Auth-Token'] = 'mytoken1'
++        req = jsonutils.dumps({'action': 'authenticate', 'headers': headers})
++
++        msg_mock = mock.patch.object(self.protocol, 'sendMessage')
++        self.addCleanup(msg_mock.stop)
++        msg_mock = msg_mock.start()
++        self.protocol.onMessage(req, False)
++
++        # Didn't send the response yet
++        self.assertEqual(0, msg_mock.call_count)
++
++        headers = self.headers.copy()
++        headers['X-Project-ID'] = '7e55e1a7f'
++        req = test_utils.create_request(consts.QUEUE_LIST, {}, headers)
++        self.protocol.onMessage(req, False)
++
++        self.assertEqual(1, msg_mock.call_count)
++        resp = jsonutils.loads(msg_mock.call_args[0][0])
++        self.assertEqual(403, resp['headers']['status'])
++
+     def test_post_between_auth(self):
+         headers = self.headers.copy()
+         headers['X-Auth-Token'] = 'mytoken1'
+@@ -90,6 +118,9 @@
+         msg_mock = msg_mock.start()
+         self.protocol.onMessage(req, False)
+ 
++        # Didn't send the response yet
++        self.assertEqual(0, msg_mock.call_count)
++
+         req = test_utils.create_request(consts.QUEUE_LIST, {}, self.headers)
+         self.protocol.onMessage(req, False)
+ 
+diff --git a/zaqar/transport/websocket/protocol.py 
b/zaqar/transport/websocket/protocol.py
+index 8c19288..78598ad 100644
+--- a/zaqar/transport/websocket/protocol.py
++++ b/zaqar/transport/websocket/protocol.py
+@@ -117,7 +117,16 @@
+             elif payload.get('action') == 'authenticate':
+                 return self._authenticate(payload, isBinary)
+             else:
++                if self._auth_strategy:
++                    auth_project = self._auth_env.get("X-PROJECT-ID")
++                    request_project = payload.get('headers', {}).get(
++                        "X-Project-ID")
++                    if not request_project or auth_project != request_project:
++                        body = {'error': 'Not authenticated.'}
++                        resp = self._handler.create_response(403, body, req)
++                        return self._send_response(resp, isBinary)
+                 resp = self._handler.process_request(req, self)
++
+             if payload.get('action') == consts.SUBSCRIPTION_CREATE:
+                 # NOTE(Eva-i): this will make further websocket
+                 # notifications encoded in the same format as the last
diff -Nru 
zaqar-20.0.0/debian/patches/CVE-2026-66139_OSSA-2026-029_Do_not_bypass_authentication_for_requests_with_EXTRA-SPEC_header.patch
 
zaqar-20.0.0/debian/patches/CVE-2026-66139_OSSA-2026-029_Do_not_bypass_authentication_for_requests_with_EXTRA-SPEC_header.patch
--- 
zaqar-20.0.0/debian/patches/CVE-2026-66139_OSSA-2026-029_Do_not_bypass_authentication_for_requests_with_EXTRA-SPEC_header.patch
     1970-01-01 01:00:00.000000000 +0100
+++ 
zaqar-20.0.0/debian/patches/CVE-2026-66139_OSSA-2026-029_Do_not_bypass_authentication_for_requests_with_EXTRA-SPEC_header.patch
     2026-10-13 14:10:33.000000000 +0200
@@ -0,0 +1,53 @@
+Author: Takashi Kajinami <[email protected]>
+Date: Wed, 22 Jul 2026 16:33:48 +0900
+Description: Do not bypass authentication for requests with EXTRA-SPEC header
+ Commit 9b6edcf6ca5aca45536fb6f5038068e506c9c673 introduced
+ the mechanism to pass down extra headers to drivers but this introduced
+ queue access with all authentication and athorization check enforced.
+ Remove the bypass to prohibit unauthenticated access.
+ .
+ Note that the "execute" interface has never been implemented actually
+ in drivers so this may have no user impact really.
+Bug: https://launchpad.net/bugs/2161254
+Bug-Debian: https://bugs.debian.org/1142858
+Change-Id: Iab3a6c3d60d97c66c693964291ebc3cdb298c1b0
+Signed-off-by: Takashi Kajinami <[email protected]>
+Origin: upstream, https://review.opendev.org/c/openstack/zaqar/+/998411
+Last-Update: 2026-07-29
+
+diff --git a/releasenotes/notes/bug-2161254-55c2748092268fb3.yaml 
b/releasenotes/notes/bug-2161254-55c2748092268fb3.yaml
+new file mode 100644
+index 0000000..a36aeae
+--- /dev/null
++++ b/releasenotes/notes/bug-2161254-55c2748092268fb3.yaml
+@@ -0,0 +1,6 @@
++---
++security:
++  - |
++    `Bug 2161254 <https://bugs.launchpad.net/zaqar/+bug/2161254>`_: Fixed
++    Requests with the ``EXTRA-SPEC`` header bypassed authentication and
++    policy check.
+diff --git a/zaqar/transport/middleware/auth.py 
b/zaqar/transport/middleware/auth.py
+index 6bc0444..1e5c53d 100644
+--- a/zaqar/transport/middleware/auth.py
++++ b/zaqar/transport/middleware/auth.py
+@@ -32,16 +32,14 @@
+ 
+     def __call__(self, environ, start_response):
+         path = environ.get('PATH_INFO')
+-        extra_spec = environ.get('HTTP_EXTRA_SPEC')
++        signature = environ.get('HTTP_URL_SIGNATURE')
++
+         # NOTE(flwang): The root path of Zaqar service shouldn't require any
+         # auth.
+         if path == '/':
+             return self._app(environ, start_response)
+ 
+-        signature = environ.get('HTTP_URL_SIGNATURE')
+-
+-        if (signature is None and extra_spec is None) or \
+-                path.startswith('/v1'):
++        if signature is None or path.startswith('/v1'):
+             return self._auth_app(environ, start_response)
+ 
+         return self._app(environ, start_response)
diff -Nru 
zaqar-20.0.0/debian/patches/CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_URL-Signature.patch
 
zaqar-20.0.0/debian/patches/CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_URL-Signature.patch
--- 
zaqar-20.0.0/debian/patches/CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_URL-Signature.patch
     1970-01-01 01:00:00.000000000 +0100
+++ 
zaqar-20.0.0/debian/patches/CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_URL-Signature.patch
     2026-10-13 14:10:33.000000000 +0200
@@ -0,0 +1,34 @@
+From: Takashi Kajinami <[email protected]>
+Date: Thu, 24 Sep 2026 22:46:06 +0900
+Description: Fix authentication bypass by empty URL-Signature
+Bug: https://launchpad.net/bugs/2164987
+Bug-Debian: https://bugs.debian.org/1148897
+Change-Id: Ib7aadf8d6de396ac9f0a11d6fcfa44849b194bf4
+Signed-off-by: Takashi Kajinami <[email protected]>
+Origin: https://review.opendev.org/c/openstack/zaqar/+/1007162
+Last-Update: 2026-09-24
+
+diff --git a/releasenotes/notes/bug-2164987-c1138c80bdc41299.yaml 
b/releasenotes/notes/bug-2164987-c1138c80bdc41299.yaml
+new file mode 100644
+index 0000000..addc084
+--- /dev/null
++++ b/releasenotes/notes/bug-2164987-c1138c80bdc41299.yaml
+@@ -0,0 +1,5 @@
++---
++security:
++  - |
++    `Bug 2164987 <https://bugs.launchpad.net/zaqar/+bug/2164987>`_ : Fixed
++    authentication bypass caused by an empty URL-Signature header.
+diff --git a/zaqar/common/transport/wsgi/helpers.py 
b/zaqar/common/transport/wsgi/helpers.py
+index a258e01..48c56fa 100644
+--- a/zaqar/common/transport/wsgi/helpers.py
++++ b/zaqar/common/transport/wsgi/helpers.py
+@@ -40,7 +40,7 @@
+     paths = headers.get('URL-PATHS', '').split(',')
+     signature = headers.get('URL-SIGNATURE')
+ 
+-    if not signature:
++    if signature is None:
+         return
+ 
+     if req.method not in methods:
diff -Nru zaqar-20.0.0/debian/patches/series zaqar-20.0.0/debian/patches/series
--- zaqar-20.0.0/debian/patches/series  2025-07-11 14:47:00.000000000 +0200
+++ zaqar-20.0.0/debian/patches/series  2026-10-13 14:10:33.000000000 +0200
@@ -1,3 +1,6 @@
 #remove-trollius-from-requirements.txt.patch
 finished-fixing-upstream-tests.patch
 package-all-files.patch
+CVE-2026-66139_OSSA-2026-029_Do_not_bypass_authentication_for_requests_with_EXTRA-SPEC_header.patch
+CVE-2026-97404_OSSA-2026-042_Fix_authentication_bypass_by_empty_URL-Signature.patch
+CVE-2026-107363_OSSA-2026-043_Prohibit_arbitrary_project-id_for_websocket_protocol_access.patch

Reply via email to