Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected] Control: affects -1 + src:aodh User: [email protected] Usertags: pu
Hi, I have uploaded aodh 20.0.0-2+deb13u2 to Trixie p-u. Here's why: [ Reason ] I'd like to get the fix for this upstream bug, reported in upstream bug tracker (ie: launchpad, which is the BTS for OpenStack): https://bugs.launchpad.net/aodh/+bug/2167496 Basically, someone repeating the project_id parameter can fool the AODH API and bypass auth. [ Impact ] What's written above. [ Tests ] My patch (which I forwarded upstream and was merged) includes new test for this issue. We've pushed the new version in production, and saw no regression. [ Risks ] Low risk because of what's just above. [ 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 Please approve aodh/aodh_20.0.0-2+deb13u2 into Trixie p-u for the next point release. Cheers, Thomas Goirand (zigo)
diff -Nru aodh-20.0.0/debian/changelog aodh-20.0.0/debian/changelog --- aodh-20.0.0/debian/changelog 2026-08-12 09:57:24.000000000 +0200 +++ aodh-20.0.0/debian/changelog 2026-11-05 12:40:16.000000000 +0100 @@ -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 <[email protected]> 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 01:00:00.000000000 +0100 +++ aodh-20.0.0/debian/patches/lp-2167496_Fix_duplicate_project_id_query_filter_bypass_project_scope.patch 2026-11-05 12:40:16.000000000 +0100 @@ -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 <[email protected]> +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 <https://bugs.launchpad.net/aodh/+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 09:57:24.000000000 +0200 +++ aodh-20.0.0/debian/patches/series 2026-11-05 12:40:16.000000000 +0100 @@ -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

