Version in base suite: 20.0.0-2 Version in overlay suite: 20.0.0-2+deb13u1 Base version: aodh_20.0.0-2+deb13u1 Target version: aodh_20.0.0-2+deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/a/aodh/aodh_20.0.0-2+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/a/aodh/aodh_20.0.0-2+deb13u2.dsc changelog | 12 + patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch | 106 ++++++++++ patches/series | 1 3 files changed, 119 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp29qhp40x/aodh_20.0.0-2+deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp29qhp40x/aodh_20.0.0-2+deb13u2.dsc: no acceptable signature found diff -Nru aodh-20.0.0/debian/changelog aodh-20.0.0/debian/changelog --- aodh-20.0.0/debian/changelog 2026-08-12 07:57:24.000000000 +0000 +++ aodh-20.0.0/debian/changelog 2026-11-05 11:40:16.000000000 +0000 @@ -1,3 +1,15 @@ +aodh (20.0.0-2+deb13u2) trixie; urgency=high + + * lp-2167496: Fix an authorization bypass in the alarm listing API where + duplicated project_id query filters could bypass project scope: + authorization validated the first filter value while the storage query + kept the last one, letting a non-admin user list another project's + alarms, including action URLs. Applied upstream patch: "Duplicated + query fields are now rejected with a 400 response" (Closes: #1153094): + - lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project....patch + + -- Thomas Goirand Thu, 05 Nov 2026 12:40:16 +0100 + aodh (20.0.0-2+deb13u1) trixie; urgency=medium * CVE-2026-76878 / OSSA-2026-036: Aodh does not correctly enforce project diff -Nru aodh-20.0.0/debian/patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch aodh-20.0.0/debian/patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch --- aodh-20.0.0/debian/patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch 1970-01-01 00:00:00.000000000 +0000 +++ aodh-20.0.0/debian/patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch 2026-11-05 11:40:16.000000000 +0000 @@ -0,0 +1,106 @@ +Description: Fix duplicate project_id query filter bypassing project scope + The alarm listing API validated the first occurrence of the project_id + query filter while building the storage filter dict from all query + objects, keeping the last one. A non-admin caller could pass their own + project_id first and a foreign project_id second, passing authorization + while the storage lookup ran against the foreign project, disclosing + that project's alarm definitions including secret-bearing action URLs. + Duplicated query fields are now rejected with a 400 response, so the + authorization check and the storage filter always operate on the same + value. +Author: Thomas Goirand +Date: Wed, 28 Oct 2026 10:42:03 +0100 +Forwarded: https://opendev.org/openstack/aodh/commit/7381d2cd6ef922fb6aed912e7366268176d42b06 +Bug: https://launchpad.net/bugs/2167496 +Bug-Debian: https://bugs.debian.org/1153094 +Assisted-By: Infomaniak Euria-Code +Last-Update: 2026-11-05 + +Index: aodh/aodh/api/controllers/v2/alarms.py +=================================================================== +--- aodh.orig/aodh/api/controllers/v2/alarms.py ++++ aodh/aodh/api/controllers/v2/alarms.py +@@ -886,6 +886,15 @@ class AlarmsController(rest.RestControll + 'op', ops, + 'only operations %s are allowed' % ALARM_QUERY_OPS_ALLOWED + ) ++ # Only one query per field is allowed: a duplicated field could ++ # make the authorization check below operate on the first value ++ # while the storage filter built at the end keeps the last one, ++ # which would bypass the project scope. ++ if len(q) != len(keys): ++ raise wsme.exc.InvalidInput( ++ 'field', keys, ++ 'duplicate query fields are not allowed' ++ ) + + if ('all_projects' in keys and + v2_utils.get_query_value(q, 'all_projects', 'boolean')): +Index: aodh/aodh/tests/functional/api/v2/test_alarm_scenarios.py +=================================================================== +--- aodh.orig/aodh/tests/functional/api/v2/test_alarm_scenarios.py ++++ aodh/aodh/tests/functional/api/v2/test_alarm_scenarios.py +@@ -249,6 +249,48 @@ class TestAlarms(TestAlarmsBase): + ) + self.assertEqual(0, len(alarms)) + ++ def _create_other_project_alarm(self): ++ alarm = copy.deepcopy(default_alarms(self.auth_headers)[0]) ++ alarm.alarm_id = 'd' ++ alarm.name = 'other-project-alarm' ++ alarm.user_id = 'other-user' ++ alarm.project_id = 'other-project' ++ self.alarm_conn.create_alarm(alarm) ++ ++ def test_get_alarm_duplicate_project_id_own_project_first(self): ++ self._create_other_project_alarm() ++ project = self.auth_headers['X-Project-Id'] ++ q = [{'field': 'project_id', 'op': 'eq', 'value': project}, ++ {'field': 'project_id', 'op': 'eq', 'value': 'other-project'}] ++ response = self.get_json( ++ '/alarms', ++ headers=self.auth_headers, ++ q=q, ++ expect_errors=True, ++ status=400 ++ ) ++ self.assertEqual(400, response.status_code) ++ faultstring = 'duplicate query fields are not allowed' ++ self.assertIn(faultstring, ++ response.json['error_message']['faultstring']) ++ ++ def test_get_alarm_duplicate_project_id_other_project_first(self): ++ self._create_other_project_alarm() ++ project = self.auth_headers['X-Project-Id'] ++ q = [{'field': 'project_id', 'op': 'eq', 'value': 'other-project'}, ++ {'field': 'project_id', 'op': 'eq', 'value': project}] ++ response = self.get_json( ++ '/alarms', ++ headers=self.auth_headers, ++ q=q, ++ expect_errors=True, ++ status=400 ++ ) ++ self.assertEqual(400, response.status_code) ++ faultstring = 'duplicate query fields are not allowed' ++ self.assertIn(faultstring, ++ response.json['error_message']['faultstring']) ++ + def test_get_alarm_forbiden(self): + pf = os.path.abspath('aodh/tests/functional/api/v2/policy.yaml-test') + self.CONF.set_override('policy_file', pf, group='oslo_policy') +Index: aodh/releasenotes/notes/fix-duplicate-project-id-query-filter-scope-f6b935de6318.yaml +=================================================================== +--- /dev/null ++++ aodh/releasenotes/notes/fix-duplicate-project-id-query-filter-scope-f6b935de6318.yaml +@@ -0,0 +1,10 @@ ++--- ++security: ++ - | ++ `Bug #2167496 `_: ++ Fixed an authorization bypass in the alarm listing API where repeated ++ ``project_id`` query filters made the authorization check operate on ++ the first value while the storage query filtered on the last one, ++ allowing a non-admin user to list another project's alarms, including ++ their action URLs. Repeated query fields are now rejected with ++ ``HTTP 400``. diff -Nru aodh-20.0.0/debian/patches/series aodh-20.0.0/debian/patches/series --- aodh-20.0.0/debian/patches/series 2026-08-12 07:57:24.000000000 +0000 +++ aodh-20.0.0/debian/patches/series 2026-11-05 11:40:16.000000000 +0000 @@ -3,3 +3,4 @@ remove-httpdomain-sphinx-ext.patch add-a-healthcheck_disable-file.patch CVE-2026-76878-aodh-lp-2161276-2025.1.patch +lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch