Bug 2550542 (CVE-2026-89419)

Summary: CVE-2026-89419 openstack-ironic: openstack-ironic: maintenance state update bypasses set_maintenance policy via generic PATCH
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: akhatavk, aos-team-art-private, asdas, dpaolell, eglynn, jdelft, jjoyce, jpretori, jschluet, jupierce, lgarciaa, lhh, mbiarnes, mburns, mgarciac, ppalepu, ppostler, prdhamdh, security-response-team, sghai, sidsharm, suppawar, vlaad
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in OpenStack Ironic. A missing authorization check in the node PATCH API allows an authenticated lessee member to change the maintenance state of a bare metal node, an operation that should be restricted to lessee managers and administrators. By sending a PATCH request to /v1/nodes/{ident} with a maintenance field, the request is processed under the generic node-update policy rather than the stricter set_maintenance policy, bypassing the intended role boundary. This could allow a lessee member to place nodes into maintenance (disrupting scheduling and availability) or to clear maintenance mode on nodes an operator intentionally marked as under maintenance.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Deadline: 2026-10-22   

Description OSIDB Bzimport 2026-10-13 14:00:33 UTC
OpenStack Ironic exposes a node management REST API. In NodesController.patch() in ironic/api/controllers/v1/node.py, a per-field policy enforcement block maps specific JSON Patch paths to the OpenStack policy rule that must be satisfied before that field can be modified. The list covered fields such as /retired (baremetal:node:update:retired), /shard, /parent_node, and /disable_power_off, but did not include /maintenance. The maintenance field was already listed in PATCH_ALLOWED_FIELDS, so PATCH /v1/nodes/{ident} with op:replace path:/maintenance value:true|false was accepted and only checked against the generic baremetal:node:update policy rule. Under Ironic project-scoped RBAC, baremetal:node:update is granted to lessee members, whereas baremetal:node:set_maintenance and baremetal:node:clear_maintenance are restricted to lessee managers and administrators. This allows a lessee member to toggle maintenance mode on nodes in their project, bypassing the intended access boundary. The dedicated maintenance API at /v1/nodes/{ident}/maintenance applies the correct set_maintenance/clear_maintenance policies. maintenance_reason was not in PATCH_ALLOWED_FIELDS before the fix (PATCH including it would be rejected with HTTP 400); only maintenance was an active exploit path via generic PATCH. Upstream fix maps /maintenance and /maintenance_reason to baremetal:node:set_maintenance (Change-Id: Ibab11b186ec0b0151e3720cd8cf9cf529ffd1112, Launchpad #2166510). Affected upstream: master and stable/2026.2 per embargo patches. Reporters: Tuomo Tanskanen (Ericsson Software Technology), Dmitry Tantsur (Red Hat). PSIRT ticket: PSIRTSUPT-25549.