Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected] Control: affects -1 + src:nova User: [email protected] Usertags: pu
Dear release team, [ Reason ] I'd like to update Nova to address CVE-2026-46448 / OSSA-2026-022 and OSSN-0101 (see bugs #1140149 and #1142113). The security team informed me that they prefer for these fixes to be pushed through p-u. [ Impact ] CVE-2026-46448 / OSSA-2026-022: Nova scheduler hint injection bypasses Placement resource claims and scheduling constraints. OSSN-0101: Nova console WebSocket proxy Origin allow-list poisoning. [ Tests ] Building the Nova package includes running 16742 tests, some of which were added specifically for the above fixes. On top of this, we've been running the patched pacakges (truth: in another OpenStack release) in production. Also, I'm constantly running the upstream functional tests suite. [ Risks ] Patches are very small, if one doesn't consider new tests. It's narly one-liners. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] 2 patches. Please allow me to upload: nova_31.0.0-6+deb13u3_source.changes to Trixie p-u. Cheers, Thomas Goirand (zigo)
diff -Nru nova-31.0.0/debian/changelog nova-31.0.0/debian/changelog --- nova-31.0.0/debian/changelog 2026-02-06 10:34:57.000000000 +0100 +++ nova-31.0.0/debian/changelog 2026-06-15 09:16:13.000000000 +0200 @@ -1,3 +1,15 @@ +nova (2:31.0.0-6+deb13u3) trixie; urgency=medium + + * CVE-2026-46448 / OSSN-2026-022: Nova scheduler hint injection bypasses + Placement resource claims and scheduling constraints. Applied upstream + patch: "Strip internal _nova-prefixed scheduler hints on create" + (Closes: #1140149). + * OSSN-0101: Nova console WebSocket proxy Origin allow-list poisoning. + Applied upstream patch: "Fix mutating global config in websocket proxy" + (Closes: #1142113). + + -- Thomas Goirand <[email protected]> Mon, 15 Jun 2026 09:16:13 +0200 + nova (2:31.0.0-6+deb13u2) trixie-security; urgency=high * CVE-2026-24708/OSSA-2026-002: By writing a malicious QCOW header to a root diff -Nru nova-31.0.0/debian/patches/CVE-2026-46448-stable-2025.1_Strip-internal-_nova-prefixed-scheduler-hints-on-create.patch nova-31.0.0/debian/patches/CVE-2026-46448-stable-2025.1_Strip-internal-_nova-prefixed-scheduler-hints-on-create.patch --- nova-31.0.0/debian/patches/CVE-2026-46448-stable-2025.1_Strip-internal-_nova-prefixed-scheduler-hints-on-create.patch 1970-01-01 01:00:00.000000000 +0100 +++ nova-31.0.0/debian/patches/CVE-2026-46448-stable-2025.1_Strip-internal-_nova-prefixed-scheduler-hints-on-create.patch 2026-06-15 09:16:13.000000000 +0200 @@ -0,0 +1,65 @@ +Author: Sylvain Bauza <[email protected]> +Date: Tue, 12 May 2026 14:31:14 +0200 +Description: CVE-2026-46448: Strip internal _nova-prefixed scheduler hints on create + User-supplied scheduler hints can include internal keys like + "_nova_check_type" which cause the scheduler to bypass Placement + candidate selection, request pre-filters, and resource claims. + This can lead to instances being created without proper resource + accounting. + . + Rather than rejecting the request, silently strip any _nova-prefixed + hints before they reach the scheduler. This is consistent with the + existing hints behavior of ignoring unknown ones and ensures the + probe attempt still costs the attacker money. +Assisted-By: Cursor +Change-Id: Iac4fef93bef0bab3060d40a9ea3e0ebd69a38c37 +Bug: https://bugs.launchpad.net/nova/+bug/2151252 +Bug-Debian: https://bugs.debian.org/1140149 +Signed-off-by: Sylvain Bauza <[email protected]> +Origin: pre-OSSA mailing list +Last-Update: 2026-06-10 + +Index: nova/nova/compute/api.py +=================================================================== +--- nova.orig/nova/compute/api.py ++++ nova/nova/compute/api.py +@@ -2232,6 +2232,10 @@ class API: + msg = _('The requested availability zone is not available') + raise exception.InvalidRequest(msg) + ++ if scheduler_hints: ++ scheduler_hints = {k: v for k, v in scheduler_hints.items() ++ if not k.startswith('_nova')} ++ + filter_properties = scheduler_utils.build_filter_properties( + scheduler_hints, forced_host, forced_node, flavor) + +Index: nova/nova/tests/unit/compute/test_api.py +=================================================================== +--- nova.orig/nova/tests/unit/compute/test_api.py ++++ nova/nova/tests/unit/compute/test_api.py +@@ -220,6 +220,24 @@ class _ComputeAPIUnitTestMixIn(object): + list_obj.obj_reset_changes() + return list_obj + ++ @mock.patch('nova.scheduler.utils.build_filter_properties') ++ def test_create_strips_internal_scheduler_hints(self, ++ mock_build_filter): ++ mock_build_filter.side_effect = ( ++ test.TestingException('stop early')) ++ flavor = self._create_flavor() ++ self.assertRaises( ++ test.TestingException, ++ self.compute_api.create, ++ self.context, flavor, 'image_id', ++ scheduler_hints={ ++ '_nova_check_type': 'rebuild', ++ '_nova_future': 'something', ++ 'group': 'valid-group-uuid', ++ }) ++ actual_hints = mock_build_filter.call_args[0][0] ++ self.assertEqual({'group': 'valid-group-uuid'}, actual_hints) ++ + @mock.patch( + 'nova.network.neutron.API.is_remote_managed_port', + new=mock.Mock(return_value=False), diff -Nru nova-31.0.0/debian/patches/OSSN-0101_Fix_mutating_global_config_in_websocket_proxy.patch nova-31.0.0/debian/patches/OSSN-0101_Fix_mutating_global_config_in_websocket_proxy.patch --- nova-31.0.0/debian/patches/OSSN-0101_Fix_mutating_global_config_in_websocket_proxy.patch 1970-01-01 01:00:00.000000000 +0100 +++ nova-31.0.0/debian/patches/OSSN-0101_Fix_mutating_global_config_in_websocket_proxy.patch 2026-06-15 09:16:13.000000000 +0200 @@ -0,0 +1,126 @@ +Author: Dan Smith <[email protected]> +Date: Thu, 02 Jul 2026 10:29:26 -0700 +Description: OSSN-0101: Fix mutating global config in websocket proxy + The websocket proxy mutates the CONF host list with the Host header + from the request, which would then poison future requests and/or + lead to a slow resource exhaustion attack. Simply making a copy before + mutation avoids the issue. +Generated-By: Claude Opus 4.6 +Bug: https://launchpad.net/bugs/2158919 +Bug-Debian: https://bugs.debian.org/1142113 +Change-Id: Ib13e479337f9b1c8b16952089d1d5f6979976b86 +Signed-off-by: Dan Smith <[email protected]> +Origin: upstream, https://review.opendev.org/c/openstack/nova/+/995958 +Last-Update: 2026-07-15 + +diff --git a/nova/console/websocketproxy.py b/nova/console/websocketproxy.py +index f71b9e1..c2b4e7f 100644 +--- a/nova/console/websocketproxy.py ++++ b/nova/console/websocketproxy.py +@@ -203,7 +203,7 @@ + expected_origin_hostname = e.split(']')[0][1:] + else: + expected_origin_hostname = e.split(':')[0] +- expected_origin_hostnames = CONF.console.allowed_origins ++ expected_origin_hostnames = list(CONF.console.allowed_origins) + expected_origin_hostnames.append(expected_origin_hostname) + origin_url = self.headers.get('Origin') + # missing origin header indicates non-browser client which is OK +diff --git a/nova/tests/unit/console/test_websocketproxy.py b/nova/tests/unit/console/test_websocketproxy.py +index 088ed8e..8c3660b 100644 +--- a/nova/tests/unit/console/test_websocketproxy.py ++++ b/nova/tests/unit/console/test_websocketproxy.py +@@ -658,6 +658,81 @@ + def test_reject_open_redirect_3_slashes(self): + self.test_reject_open_redirect(url='///example.com/%2F..') + ++ @mock.patch('nova.console.websocketproxy.NovaProxyRequestHandler.' ++ '_check_console_port') ++ @mock.patch('nova.objects.ConsoleAuthToken.validate') ++ def test_host_header_does_not_poison_allowed_origins( ++ self, validate, check_port): ++ """Verify that the Host header from one request does not persist in ++ CONF.console.allowed_origins and affect subsequent origin checks. ++ ++ Regression test for bug 2158919. ++ """ ++ params = { ++ 'id': 1, ++ 'token': '123-456-789', ++ 'instance_uuid': uuids.instance, ++ 'host': 'node1', ++ 'port': '10000', ++ 'console_type': 'novnc', ++ 'access_url_base': 'https://example.net:6080' ++ } ++ validate.return_value = objects.ConsoleAuthToken(**params) ++ ++ self.wh.socket.return_value = '<socket>' ++ self.wh.path = "http://127.0.0.1/?token=123-456-789" ++ self.wh.headers = self.fake_header ++ ++ original_conf_origins = list(CONF.console.allowed_origins) ++ ++ self.wh.new_websocket_client() ++ ++ self.assertEqual(original_conf_origins, ++ CONF.console.allowed_origins) ++ ++ @mock.patch('nova.console.websocketproxy.NovaProxyRequestHandler.' ++ '_check_console_port') ++ @mock.patch('nova.objects.ConsoleAuthToken.validate') ++ def test_previous_host_does_not_bypass_origin_check( ++ self, validate, check_port): ++ """Verify that a Host header from a prior request cannot be used to ++ bypass the origin check on a subsequent request. ++ ++ Regression test for bug 2158919. ++ """ ++ params = { ++ 'id': 1, ++ 'token': '123-456-789', ++ 'instance_uuid': uuids.instance, ++ 'host': 'node1', ++ 'port': '10000', ++ 'console_type': 'novnc', ++ 'access_url_base': 'https://example.net:6080' ++ } ++ validate.return_value = objects.ConsoleAuthToken(**params) ++ ++ self.wh.socket.return_value = '<socket>' ++ self.wh.path = "http://127.0.0.1/?token=123-456-789" ++ ++ # First request: Host header introduces evil.com ++ self.wh.headers = { ++ 'cookie': 'token="123-456-789"', ++ 'Origin': 'https://evil.com:6080', ++ 'Host': 'evil.com:6080', ++ } ++ self.wh.new_websocket_client() ++ ++ # Second request: Origin is evil.com but Host is legitimate. ++ # This must be rejected — evil.com should not have been persisted ++ # into the allow-list by the first request. ++ self.wh.headers = { ++ 'cookie': 'token="123-456-789"', ++ 'Origin': 'https://evil.com:6080', ++ 'Host': 'example.net:6080', ++ } ++ self.assertRaises(exception.ValidationError, ++ self.wh.new_websocket_client) ++ + @mock.patch('nova.objects.ConsoleAuthToken.validate') + def test_no_compute_rpcapi_with_invalid_token(self, mock_validate): + """Tests that we don't create a ComputeAPI object until we actually +diff --git a/releasenotes/notes/console-token-origin-poison-f251ab9e3f63d6bd.yaml b/releasenotes/notes/console-token-origin-poison-f251ab9e3f63d6bd.yaml +new file mode 100644 +index 0000000..8f8c3df +--- /dev/null ++++ b/releasenotes/notes/console-token-origin-poison-f251ab9e3f63d6bd.yaml +@@ -0,0 +1,6 @@ ++--- ++security: ++ - | ++ Bug #2158919 is fixed, which involved an authenticated user able to poison ++ the server-side allowed origins list (and potentially exhaust memory by ++ extending it until failure). diff -Nru nova-31.0.0/debian/patches/series nova-31.0.0/debian/patches/series --- nova-31.0.0/debian/patches/series 2026-02-06 10:34:57.000000000 +0100 +++ nova-31.0.0/debian/patches/series 2026-06-15 09:16:13.000000000 +0200 @@ -7,3 +7,5 @@ Fix-neutron-client-dict-grabbing.patch OSSN-0094_restrict_swap_volume_to_cinder.patch cve-2026-24708-make-disk.extend-pass-format-to-qemu-img-2025.1.patch +CVE-2026-46448-stable-2025.1_Strip-internal-_nova-prefixed-scheduler-hints-on-create.patch +OSSN-0101_Fix_mutating_global_config_in_websocket_proxy.patch

