Safeguard
Supply Chain Security•

OpenStack Ironic OSSA-2026-047/048 and oslo.utils LUKS key logging

Two Ironic flaws (CVE-2026-90458, CVE-2026-89419) and an oslo.utils LUKS key logging note. No fixed PyPI releases yet; patch, set log levels, rotate keys.

Safeguard Security Team
37 min read

On 22 October 2026 OpenStack published two Ironic advisories, OSSA-2026-047 (CVE-2026-90458, Redfish path injection to the BMC) and OSSA-2026-048 (CVE-2026-89419, a maintenance policy bypass), plus security note OSSN-0111: oslo.utils 10.1.0 to 10.2.x can log LUKS key material at DEBUG. No fixed PyPI release exists yet. Apply the Gerrit patches, raise the log level, and rotate any exposed keys.

The three items fail in different ways. The two Ironic bugs are authorization problems in the bare metal provisioning service, both need an authenticated user with an existing role, and both are fixed in git on every branch. The oslo.utils note is quieter and, for the people it touches, worse: a shared library wrote decryption key material into ordinary logs. A code update stops new lines being written. It does nothing about what already sits in a log archive or backup. For that, the only real fix is a new key.

No exploitation of any of the three has been reported in the advisories, CVE records or bug trackers we checked on 24 October 2026. This post covers affected versions, the fixing commits, why pip install --upgrade does not help yet, and the operator steps that close the gap.

What happened

The Metal3.io Security Team reported both Ironic bugs in early September. Metal3 is the Kubernetes project that drives bare metal hosts through Ironic. Fixes were written and reviewed over about seven weeks, then everything landed on one day. The oslo.utils bug moved faster: filed on 21 October, published the next morning. All times are UTC, converted where a source used another zone.

Date and time (UTC, 2026)EventSource
4 Sep, 15:04Launchpad bug 2166507 filed: Redfish vendor_passthru subscription ID concatenated into the Redfish pathLaunchpad 2166507
4 Sep, 15:14Launchpad bug 2166510 filed: node PATCH bypasses the maintenance policiesLaunchpad 2166510
8 Sep, 15:46Fix for the maintenance bypass authored ("Security: Fix maintenance state update policy bypass")Gerrit 1011861
11 Sep, 18:17CVE-2026-89419 reservedCVE record
11 Sep, 21:01CVE-2026-90458 reservedCVE record
17 Sep, 14:59Fix for the Redfish path injection authored ("Validate BMC subscription IDs in Redfish vendor passthrough methods")Gerrit 1011860
21 Sep, 08:05Ironic 39.0.0 uploaded to PyPI, still the newest Ironic release on 24 OctPyPI
21 Oct, 04:47Launchpad bug 2171574 filed: "LUKSInspector logs LUKS key material at DEBUG level"Launchpad 2171574
21 Oct, 06:40Fix "Stop logging LUKS key material" authored by Abhishek KekaneGerrit 1011661
22 Oct, 14:12OSSN-0111 posted to oss-security (10:12:46 EDT)oss-security 2026/10/22/9
22 Oct, 15:49OSSA-2026-047 posted to oss-security (08:49:48 PDT)oss-security 2026/10/22/6
22 Oct, 15:52OSSA-2026-048 posted to oss-security (08:52:57 PDT)oss-security 2026/10/22/7
22 Oct, 16:03OSSA tasks on both Ironic bugs set to Fix ReleasedLaunchpad
22 Oct, 16:31oslo.utils fix merged to masterGerrit 1011661
22 Oct, 17:37Redfish fix merged to Ironic masterGerrit 1011860
22 Oct, 17:51Maintenance fix merged to Ironic masterGerrit 1011861
22 Oct, 18:38 and 18:40Both fixes merged to stable/2026.2 (Hibiscus)Gerrit 1011862, 1011863
22 Oct, 19:56 and 20:04Both fixes merged to stable/2026.1 (Gazpacho)Gerrit 1011864, 1011865
22 Oct, 20:04Both fixes merged to bugfix/38.0 and bugfix/37.0Gerrit 1011872 to 1011875
22 Oct, 23:45 and 23 Oct, 13:12Both fixes merged to stable/2025.2 (Flamingo)Gerrit 1011866, 1011867
23 Oct, 03:44CVE-2026-89419 published, CVSS 3.1 base score 5.0CVE record
23 Oct, 03:50CVE-2026-90458 published, CVSS 3.1 base score 5.4CVE record
23 Oct, 15:23 and 15:37Both fixes merged to stable/2025.1 (Epoxy)Gerrit 1011868, 1011869
23 Oct, 19:25 and 19:26Both fixes merged to unmaintained/2024.1 (Caracal)Gerrit 1011870, 1011871
24 OctNo new Ironic or oslo.utils release on PyPI or in git tags; NVD lists both CVEs as "Awaiting Analysis"PyPI, OpenDev tags, NVD

Every Ironic branch had a merged fix within about 28 hours of disclosure. But a merged fix is not a release. On 24 October the newest Ironic on PyPI was 39.0.0 (21 September), the newest oslo.utils was 10.2.0 (24 August), and we found no pending release request for either project. If you install from PyPI or distribution packages, you are running vulnerable code unless you have acted.

Who is affected

OSSA-2026-047 and OSSA-2026-048: Ironic

The advisories give these affected ranges. We have mapped them to OpenStack series using the deliverable files in the openstack/releases repository.

SeriesIronic versions in the seriesOSSA-2026-047 (CVE-2026-90458)OSSA-2026-048 (CVE-2026-89419)Patch (047 / 048)New release planned?
2024.1 Caracal (unmaintained)23.1.0 to 24.1.5Affected from 18.1.0Affected from 17.0.01011870 / 1011871No, git only
2025.1 Epoxy27.0.0 to 29.1.0AffectedAffected1011868 / 1011869Expected, not yet tagged
2025.2 Flamingo30.0.0 to 32.1.0AffectedAffected1011866 / 1011867Expected, not yet tagged
2026.1 Gazpacho33.0.0 to 35.1.0AffectedAffected1011864 / 1011865Expected, not yet tagged
2026.2 Hibiscus36.0.0 to 39.0.0AffectedAffected1011862 / 1011863Expected, not yet tagged
bugfix/37.0 and bugfix/38.037.0.x, 38.0.xAffectedAffected1011874, 1011872 / 1011875, 1011873No, git only
2027.1 Indri (development)none releasedFixed on masterFixed on master1011860 / 1011861Next release

The OSSA pages state the ranges as >=18.1.0 <=29.1.1, >30.0.0 <=32.1.1, >33.0.0 <=35.1.1, >36.0.0 <=39.0.1 for 047, and the same with >=17.0.0 as the first bound for 048. The CVE records, published by MITRE, use exclusive upper bounds ("18.1.0 up to but not including 29.1.1" and so on) and describe the bug as affecting "Ironic before 39.0.1". So the OSSA counts 29.1.1, 32.1.1, 35.1.1 and 39.0.1 as affected while the CVE record treats them as the first fixed versions. None of those four exists on PyPI or as a git tag yet, so today every released Ironic in the listed series is affected. When point releases appear, check their release notes for the two security entries before trusting the number.

Two conditions narrow 047. It only matters for nodes enrolled with a Redfish hardware type, and the caller needs baremetal:node:vendor_passthru, which default policy grants only to a system scoped administrator (role:admin and system_scope:all). A comment in Ironic's policy code notes that some operators extend vendor passthru to owner administrators. If you have, more people can reach this bug.

048 only changes anything for nodes with a lessee project set. Default permissions are unchanged for node.owner members and system scoped users. The people who gain are lessee project members, who should not be able to toggle maintenance at all.

Metal3 and OpenShift bare metal

Metal3, and products that bundle it, inherit these bugs through the Ironic image they ship. We found no separate Metal3 or vendor advisory naming these CVEs on 24 October and did not check product versions, so ask your platform vendor which Ironic commit their image carries. Standalone Ironic without Keystone often has a simpler authentication model where whoever holds the API credentials has full rights, so the "system scoped administrator" precondition can describe more people and automation than in a full OpenStack cloud.

OSSN-0111: oslo.utils

ItemValueSource
Packageoslo.utils (PyPI)OSSN-0111
Affected>=10.1.0 <10.3.0OSSN-0111
Released affected versions10.1.0 (28 May 2026), 10.1.1 (9 Jun 2026), 10.2.0 (24 Aug 2026)PyPI
Fixed10.3.0, not yet released on 24 Oct; fix on master as commit 8d11103f2df4f60aa40dc91e6934c1dd1200593dOSSN-0111, Gerrit 1011661
Stable backportNone proposed on Gerrit as of 24 OctGerrit query
CVENone; OSSN is a security note, and the Launchpad OSSA task is marked "Won't Fix"Launchpad 2171574
Exploitation reportedNoneOSSN-0111, oss-security

Per the openstack/releases deliverable files, oslo.utils 10.1.0, 10.1.1 and 10.2.0 are all 2026.2 Hibiscus releases, and Hibiscus upper constraints pin oslo.utils===10.2.0. Gazpacho pins 10.0.1 and Flamingo 9.1.0, both below the range. So Hibiscus deployments built from upstream constraints have an affected version; older series probably do not unless someone pulled a newer oslo.utils in. Distribution packages can differ, so check what is installed.

The version is only the first of four conditions the note says must all be true:

  1. oslo.utils 10.1.0 or later is installed.
  2. Something calls the LUKS inspector with a passphrase.
  3. DEBUG logging is enabled for the oslo_utils.imageutils._luks logger.
  4. The resulting logs are kept, or can be read by someone who should not see them.

Condition two is the hard one. The note does not say which services pass a passphrase. The inspector takes it as a parameter named luks_passphrase, and OpenDev's public code search on 24 October found that name only inside oslo.utils and its tests. That suggests the risk sits mostly with custom tooling that inspects encrypted images, but it does not prove any service is or is not affected by default. Search your own code and plugins.

How it works, in plain language

OSSA-2026-047: a subscription ID that became part of a URL

Redfish is the DMTF standard HTTP API that modern baseboard management controllers (BMCs) expose. A BMC is the small, always on computer inside a server that controls power, firmware, virtual media and console access. Ironic talks to BMCs with an administrator account so it can power servers on, mount boot media and so on.

Ironic's Redfish management interface offers vendor passthru methods for Redfish event subscriptions: create one, list them, get one and delete one. To get or delete a subscription, the caller supplies the subscription's ID. Before the fix, Ironic checked only that an ID was present, then appended it to the subscriptions path and sent the request to the BMC. The fix's commit message says that an attacker could craft an ID that would let them "issue arbitrary HTTP DELETEs" and GETs "on the BMC's Redfish root under the conductor's BMC-admin identity". In other words, the request goes out with the BMC administrator credentials Ironic holds, and the path is no longer limited to event subscriptions. The advisory's worst case is deleting user accounts from the BMC's Redfish service.

The fix adds a validator, is_bmc_subscription_id_valid, that rejects characters RFC 1738 treats as unsafe or reserved and the two dot sequence used for traversal. The release note admits "there's no explicit specification" for a valid subscription ID, so the check is a deny list: reasonable for a field with no schema, and a reminder never to build an outbound URL from user input without encoding it.

Why does this matter if the caller is already a system administrator? Because Ironic API admin and BMC admin are different trust boundaries. Operators give staff, automation and CI jobs system scope in Ironic without meaning to hand them raw administrative access to every BMC, which is why Ironic hides BMC credentials from API responses. This bug let an API role reach past that wall.

OSSA-2026-048: two doors into the same room

Ironic has a dedicated maintenance endpoint, /v1/nodes/{ident}/maintenance, guarded by the baremetal:node:set_maintenance and baremetal:node:clear_maintenance policies. Under default policy, a lessee project needs the admin or manager role to use it. But a node's maintenance and maintenance_reason fields can also be changed with a general PATCH /v1/nodes/{ident}. That path is guarded by baremetal:node:update, plus a list of field specific policies for sensitive fields. The maintenance fields were missing from that list, so the generic update policy was the only check. The default for baremetal:node:update allows project members, so a member of the lessee project could flip maintenance through the side door.

The fix is three lines in ironic/api/controllers/v1/node.py: it adds /maintenance and /maintenance_reason to the patch validation table and maps both to baremetal:node:set_maintenance. The same change adds 52 lines of role based access control test cases for project scoped users.

Maintenance mode tells Ironic to leave a node alone while someone works on it. The advisory describes no consequence beyond changing that setting, and the CVE record rates it 5.0 with high attack complexity. A lessee member could take a leased node out of normal handling or bring back one an operator had parked: an operational risk, not a takeover.

OSSN-0111: a debug trace that printed the key

LUKS is the standard Linux disk encryption format. A LUKS volume has a random master key (also called the volume key) that encrypts the data. The passphrase does not encrypt data directly. It is run through PBKDF2 to derive a key that unlocks one copy of the master key stored in a key slot. If you know the master key, you do not need the passphrase at all.

oslo.utils has a format inspector, used across OpenStack to check what an uploaded disk image really is before trusting it. Since 10.1.0 that inspector can look inside a LUKSv1 image: given a passphrase, it recovers the master key, decrypts the first block and checks the inner format. While doing that, the _luks module logged its intermediate values at DEBUG. The fix removed exactly five log calls, which printed:

Removed log line labelWhat it contained (per OSSN-0111 and the fix)
Derived key:First 32 hex characters of the PBKDF2 derived key
First 32 bytes:The first 32 bytes of the decrypted split key material
Master key candidate:The full recovered master key candidate, hex encoded
Computed digest:The computed master key digest
Expected digest:The master key digest from the LUKS header

The passphrase itself was never logged. That is small comfort: the OSSN states plainly that when the passphrase is correct, the logged master key candidate "can decrypt the LUKSv1 image". Anyone with the log line and a copy of the image has the plaintext.

This is why an upgrade alone is not enough. The fix's release note says it "prevents future disclosure only". Logs are copied to more places, kept longer and read by more people than any key manager, and the master key does not expire. Changing the LUKS passphrase does not change it either, because a passphrase change rewraps the same master key in a new key slot. The only way to retire an exposed master key is to re-encrypt with a new one.

Technical details

Identifiers and scores

FieldOSSA-2026-047OSSA-2026-048OSSN-0111
TitleRedfish vendor_passthru method allows path injection via IDIronic allows generic node update for maintenance settingoslo.utils can log LUKS key material
CVECVE-2026-90458CVE-2026-89419None
CVE assignerMITREMITREn/a
CVSS 3.1 (CVE record)5.4 Medium, CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N5.0 Medium, CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:LNone published
CWE (CVE record)CWE-1287 Improper Validation of Specified Type of InputCWE-424 Improper Protection of Alternate Pathn/a
NVD status on 24 OctAwaiting AnalysisAwaiting Analysisn/a
Launchpad bug2166507 (filed 4 Sep 2026)2166510 (filed 4 Sep 2026)2171574 (filed 21 Oct 2026)
Launchpad importance (ironic task)MediumCriticalUndecided
Reporter or creditTuomo Tanskanen (Ericsson Software Technology) and Dmitry Tantsur (Red Hat), Metal3.io Security TeamSameAbhishek Kekane, Red Hat
Fix author (Gerrit)Clif HouckAfonne-CIDAbhishek Kekane
Exploitation reportedNoneNoneNone

The OSSA pages themselves do not carry a CVSS score. The scores above come from the CVE records. NVD had not added its own analysis when we checked. Launchpad's "Critical" importance on 048 is a triage label in the bug tracker, not a severity score, and it disagrees with the 5.0 in the CVE record. We would plan around the CVE score and the actual preconditions.

Fix commits per branch

These are the merged Gerrit revisions. A Gerrit revision is the commit that was reviewed; it should be an ancestor of the branch head after merge, which is what the verification step below checks.

Project and branchChangeCommitMerged (UTC)
oslo.utils master1011661 "Stop logging LUKS key material"8d11103f2df4f60aa40dc91e6934c1dd1200593d22 Oct 16:31
ironic master (047)10118602ce8a6b87fda181c99b98a07f20383901dc4158822 Oct 17:37
ironic master (048)1011861960208e4cf9c71538ab57c8009850708330fec3422 Oct 17:51
ironic stable/2026.2 (047)1011862993565f27fdc0386781ecb6864054dbde99f731522 Oct 18:38
ironic stable/2026.2 (048)101186339ce09ec3b0d4de31bb092f1507784a0240b7aaa22 Oct 18:40
ironic stable/2026.1 (047)1011864a965b6ebd1bce07789f99d016f12e471a2fa51bb22 Oct 19:56
ironic stable/2026.1 (048)1011865c85c71ec8a17343c4052f465bf3a72bc62b6489622 Oct 20:04
ironic stable/2025.2 (047 / 048)1011866 / 10118675b55dc9adf3c / f53cdc7699b1 (short)22 Oct 23:45 / 23 Oct 13:12
ironic stable/2025.1 (047 / 048)1011868 / 10118699686eaa1d8c9 / d4e6c36dc006 (short)23 Oct 15:23 / 15:37
ironic unmaintained/2024.1 (047 / 048)1011870 / 10118713a2cc30bc50f / 65125c80b9e4 (short)23 Oct 19:25 / 19:26
ironic bugfix/38.0 (047 / 048)1011872 / 10118738ffebf219fb7 / 61b0a75cdc8d (short)22 Oct 20:04
ironic bugfix/37.0 (047 / 048)1011874 / 1011875ab6997711869 / 8098e4c56d32 (short)22 Oct 20:04

Files touched, from Gerrit:

  • 047 (1011860): ironic/common/validate.py (new, 36 lines), ironic/drivers/modules/redfish/vendor.py (25 added, 8 removed), unit tests in ironic/tests/unit/common/test_validate.py and ironic/tests/unit/drivers/modules/redfish/test_vendor.py, and release note validate-bmc-subscription-id-redfish-vendor-passthru-50b5a20681a9e039.yaml.
  • 048 (1011861): ironic/api/controllers/v1/node.py (3 added, 1 removed), ironic/tests/unit/api/controllers/v1/test_node.py, ironic/tests/unit/api/test_rbac_project_scoped.yaml (52 added), release note cve-2026-89419-maintenance-policy-c3a38911afa411d2.yaml.
  • OSSN-0111 (1011661): oslo_utils/imageutils/_luks.py (5 lines removed), oslo_utils/tests/imageutils/test_luks.py (27 added), release note avoid-luks-key-logging-6c3a2e64d1a05e71.yaml.

Behaviour after the fix

  • 047: a get or delete subscription call with an invalid ID now returns InvalidParameterValue instead of reaching the BMC. Test with your BMC models, since the field has no schema.
  • 048: a node PATCH touching /maintenance or /maintenance_reason is now checked against baremetal:node:set_maintenance, so lessee member automation that relied on generic PATCH will get 403 responses.
  • OSSN-0111: the inspector still logs non sensitive progress at DEBUG, such as "Deriving key from passphrase using PBKDF2", the split key size, the stripe count, the digest salt prefix and the iteration count. Only the five key material lines are gone.

Indicators

No source lists indicators of compromise, since no exploitation is reported. The useful signals are the five log labels above, Redfish subscription passthru calls, and node PATCH requests from lessee projects.

Why there is a fix but no release

A security fix lands in git first; a new version is then proposed in the openstack/releases repository, and only after that merges does a tarball reach PyPI and distributions. On 24 October that step had not started for either project. The only open Ironic item we found there was a change opened on 16 October to move 2025.1 Epoxy to "unmaintained". If that completes before an Epoxy point release, Epoxy may end up "git only" like Caracal. Watch it rather than assume.

The advisories say unmaintained/2024.1, bugfix/37.0 and bugfix/38.0 get merged patches but "no new releases". There, the git patch is the final answer: build from the branch, carry the patch, or move series.

oslo.utils has its own wrinkle. The fix is on master only. oslo.utils has a stable/2026.2 branch, and Hibiscus pins 10.2.0, but we found no backport proposed. A 10.3.0 from master will not reach Hibiscus deployments that follow upper constraints, so the log level workaround is the main defence there for now.

How to check whether you are exposed

Step 1: find what is installed

On a host or in a container that runs Ironic or any OpenStack service:

# Python package versions inside the service's environment
python3 -m pip show ironic oslo.utils 2>/dev/null | grep -E '^(Name|Version|Location)'

# Distribution packages (names vary by distro)
rpm -qa | grep -Ei 'ironic|oslo-utils|oslo\.utils'
dpkg -l | grep -Ei 'ironic|oslo-utils'

# In containerised deployments, check every image, not just one host
for img in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep -Ei 'ironic|glance|nova|cinder'); do
  echo "== $img"
  docker run --rm --entrypoint python3 "$img" -m pip show oslo.utils ironic 2>/dev/null | grep -E '^(Name|Version)'
done

Remember that installs from git report a pbr development version such as 39.0.1.dev3. A scanner keyed on version strings may misjudge those in either direction, so for git based installs verify the commit (Step 4) rather than trusting the number.

Step 2: Ironic, which nodes and which people are in scope for 047

# Nodes using a Redfish management interface
openstack baremetal node list --fields uuid name driver management_interface

# Who holds system scoped admin (needs Keystone admin rights)
openstack role assignment list --system all --role admin --names

# Any local override of the vendor passthru policy
grep -n 'baremetal:node:vendor_passthru' /etc/ironic/policy.yaml /etc/ironic/policy.json 2>/dev/null

If the policy grep returns a line, read it carefully. The default is system scoped admin only. Anything wider means more people could have reached the Redfish bug.

Step 3: Ironic, which nodes are in scope for 048

# Nodes with a lessee set: only these are affected by 048
openstack baremetal node list --fields uuid name owner lessee maintenance maintenance_reason

# Nodes currently in maintenance, to compare against your change records
openstack baremetal node list --maintenance --fields uuid name lessee maintenance_reason

Any node in maintenance that nobody on your team put there, or a node that came out of maintenance without a ticket, deserves a look. If you keep Ironic API access logs, look for PATCH /v1/nodes/ requests made with lessee project tokens. Access logs usually do not include request bodies, so you will need correlated notifications or audit middleware output to see which fields changed.

Step 4: Ironic, verify a patched build

If you build from git, confirm that both fixes are ancestors of what you deploy. For 2026.2:

git clone https://opendev.org/openstack/ironic && cd ironic
git checkout stable/2026.2
git merge-base --is-ancestor 993565f27fdc0386781ecb6864054dbde99f7315 HEAD && echo "047 fix present"
git merge-base --is-ancestor 39ce09ec3b0d4de31bb092f1507784a0240b7aaa HEAD && echo "048 fix present"

# Quick source check on an installed copy
python3 - <<'EOF'
import inspect, ironic.common, os
p = os.path.join(os.path.dirname(ironic.common.__file__), "validate.py")
print("validate.py present:", os.path.exists(p))
from ironic.api.controllers.v1 import node
src = inspect.getsource(node)
print("maintenance mapped to set_maintenance:", "('/maintenance', 'baremetal:node:set_maintenance')" in src)
EOF

Swap in the commit IDs from the table above for other branches.

Step 5: oslo.utils, check the other three conditions

# Is DEBUG on? oslo.log's 'debug' option sets the root logger to DEBUG
grep -RniE '^\s*debug\s*=\s*true' /etc/glance /etc/nova /etc/cinder /etc/ironic 2>/dev/null

# Is the _luks logger set explicitly?
grep -RniE 'default_log_levels|oslo_utils' /etc/glance /etc/nova /etc/cinder /etc/ironic 2>/dev/null

# Any external logging config that could set DEBUG
grep -RniE 'log_config_append' /etc/glance /etc/nova /etc/cinder /etc/ironic 2>/dev/null

# Does anything you run pass a passphrase to the inspector?
grep -RIn 'luks_passphrase' /opt /usr/lib/python3*/site-packages /usr/local/lib/python3*/site-packages 2>/dev/null \
  | grep -v 'oslo_utils/'

If DEBUG has never been on, or nothing passes luks_passphrase, you were not exposed through this route. Keep the result as evidence for the record.

Step 6: oslo.utils, search retained logs

# Local and rotated logs
PATTERN='Master key candidate:|Derived key:|First 32 bytes:|Computed digest:|Expected digest:'
grep -RnE "$PATTERN" /var/log 2>/dev/null
zgrep -nE "$PATTERN" /var/log/*/*.gz 2>/dev/null

# Container logs
for c in $(docker ps -a --format '{{.Names}}'); do
  docker logs "$c" 2>&1 | grep -E "$PATTERN" >/dev/null && echo "hit in $c"
done

For central logging, search on the logger name oslo_utils.imageutils._luks as well as the labels. oslo.log's default format includes the logger name, so most pipelines index it. Do not paste matching lines into tickets or chat; treat each hit as a secret and record only where it was found.

What to do now

  1. Raise the _luks log level today, on every service host and image. This is the documented mitigation in OSSN-0111. In each affected service's configuration file:

    [DEFAULT]
    default_log_levels = oslo_utils.imageutils._luks=INFO,<your existing defaults>
    

    default_log_levels replaces the whole built in list rather than adding to it, so copy the service's existing defaults into the line. You can print oslo.log's generic list with python3 -c "from oslo_log import log; print(','.join(log.get_default_log_levels()))", but some services set their own defaults in code, so check the service's sample configuration as well. For non OpenStack Python tools that use the inspector directly, set the logger level in code before inspection runs, for example logging.getLogger("oslo_utils.imageutils._luks").setLevel(logging.INFO). That last example is our suggestion, not text from the note.

  2. Lock down log access. Restrict who can read service logs, log archives, central logging indexes and backups, as the OSSN recommends. If you find hits in Step 6, also restrict snapshots of those indexes.

  3. If key material was logged, re-encrypt with a new master key. The OSSN and the fix's release note both say this. Changing the passphrase is not enough. For LUKS images stored in an image service, the clean path is: decrypt the image in a controlled environment, create a fresh LUKS container (which generates a new master key), upload it as a new image, update references, then delete the old image and every cached or backed up copy. For LUKS2 volumes you manage directly, cryptsetup reencrypt can generate a new volume key in place; LUKSv1 needs the older offline re-encryption tooling or a copy. Rotate the passphrase secret in your key manager too, as hygiene.

  4. Purge the log lines from archives and indexes once you have recorded where they were, following your retention and legal hold rules. Purging does not undo exposure, so do it after step 3, not instead of it.

  5. Patch Ironic. Pick one:

    • Install your distribution's fixed packages when they appear, and confirm the changelog cites CVE-2026-90458 and CVE-2026-89419.

    • Build from the stable branch head after Step 4 confirms both commits are present.

    • Cherry pick the two Gerrit changes for your branch onto your own build:

      # Example for stable/2026.2; use the change refs for your branch
      git fetch https://review.opendev.org/openstack/ironic refs/changes/62/1011862/1 && git cherry-pick FETCH_HEAD
      git fetch https://review.opendev.org/openstack/ironic refs/changes/63/1011863/3 && git cherry-pick FETCH_HEAD
      

    Then rebuild your Ironic images, redeploy the API and conductor services, and run your normal provisioning smoke tests.

  6. Until Ironic is patched, shrink the attack surface. For 047, review the list of system scoped admins and remove ones that do not need it, and revert any widening of baremetal:node:vendor_passthru. For 048, you can make generic node updates require the same rights as maintenance changes by setting baremetal:node:update in policy.yaml to the expanded check string of baremetal:node:set_maintenance, which you can print with oslopolicy-policy-generator --namespace ironic. That trade off removes generic PATCH rights from lessee members entirely, which may break lessee workflows that edit other fields, so test before rolling out.

  7. Audit your BMCs. For Redfish enrolled nodes, compare each BMC's account list and event subscriptions against what you expect. A read only check from your management network looks like this:

    curl -sk -u "$BMC_USER" "https://$BMC_HOST/redfish/v1/AccountService/Accounts" | python3 -m json.tool
    curl -sk -u "$BMC_USER" "https://$BMC_HOST/redfish/v1/EventService/Subscriptions" | python3 -m json.tool
    # Ironic's own view of subscriptions on a node
    openstack baremetal node passthru call --http-method GET <node> get_all_subscriptions
    

    Missing accounts or unexpected subscriptions are worth an investigation, even though no exploitation has been reported.

  8. Upgrade oslo.utils when 10.3.0 or a backport ships, and keep the log level setting anyway. There is no reason for a production service to log key derivation internals at DEBUG.

Common mistakes

  • Treating "fix merged" as "fixed". Merged on stable/2026.2 means nothing for a host that installs Ironic 39.0.0 from PyPI. Check what is running.
  • Changing the LUKS passphrase and calling it done. The logged value is the master key. A new passphrase wraps the same master key.
  • Setting default_log_levels to a single entry. It replaces the whole default list, which can suddenly make other libraries very noisy or very quiet. Copy the existing defaults.
  • Assuming a CVE scanner will flag OSSN-0111. It has no CVE. You need a version inventory and a rule for the >=10.1.0 <10.3.0 range.
  • Reading 048 as critical because of a tracker label. The CVE score is 5.0 and it needs a lessee member role.

What changed since first reports

  • The advisories went out without CVSS scores; the CVE records published on 23 October added 5.0 and 5.4, with exclusive upper bounds that differ from the OSSA's inclusive ones.
  • Backports to 2025.2, 2025.1 and 2024.1 merged after disclosure. All 16 Ironic patches were merged by 23 October 19:26 UTC.
  • The oslo.utils bug's OSSA task was set to "Won't Fix", matching the decision to publish a note rather than a CVE advisory.

Open questions

  • When will Ironic 39.0.1 (and 29.1.1, 32.1.1, 35.1.1) and oslo.utils 10.3.0 be released? No release request was open on 24 October.
  • Will the oslo.utils fix be backported to stable/2026.2, where all affected releases live?
  • Which, if any, upstream OpenStack service passes a LUKS passphrase to the inspector in a default deployment? The note does not say, and public code search found none.
  • Which Metal3 and OpenShift bare metal builds include the vulnerable Ironic code, and when will vendor images carry the fixes?
  • Will NVD's analysis change the scores from the CVE records?

What would have helped

Practices any team can use

  • Treat logs as a store of secrets. Keep production off DEBUG, make DEBUG a time limited change with an owner, and give log archives access control that matches their contents.
  • Know library versions, not just service versions. "Which images contain oslo.utils 10.1.0 to 10.2.0?" should take minutes to answer.
  • Track security notes, not only CVEs. Route OSSNs into the same queue as advisories.
  • Be able to rebuild from a commit. When fixes land in git before releases, teams that can ship an image from a pinned commit close the gap the same day.
  • Separate API admin from BMC admin. Give Ironic's BMC account only the Redfish privileges it needs, keep system scoped Ironic admins few, and audit BMC accounts on a schedule.
  • Test policy with the roles you hand out. Policy tests with lessee member, lessee manager and owner tokens catch side doors like 048.
  • Plan key rotation before you need it. Know how you would re-encrypt every LUKS image you store, and test it once.

Where Safeguard fits

  • Find every place a vulnerable version runs. safeguard scan --dir . on your deployment repositories, safeguard scan --image <name> on each service image, or safeguard scan --sbom <file> on SBOMs you already produce gives a full dependency inventory, written as JSON under ./output. The platform then shows which projects contain a given component and version, so "which images have oslo.utils 10.2.0 or ironic 39.0.0" becomes one query instead of a host by host hunt. Our guide to finding affected products fast with SBOMs walks through that workflow.
  • Match the CVEs. Vulnerability matching against vulnerability databases covers CVE-2026-90458 and CVE-2026-89419 as those records propagate. OSSN-0111 has no CVE, so no CVE matcher, ours included, will flag it on its own; use the inventory to find the version range.
  • Ship the fix as a pull request. When 10.3.0 or the Ironic point releases are published, autonomous remediation can open tested, policy gated pull requests that move pinned versions, with reachability analysis to rank them. It ships switched off, so your team chooses what runs on its own.
  • Do the patch work with approval. The Safeguard CLI's assistant can edit code and run commands, such as adding the cherry picks to your image build or adding the default_log_levels line to your configuration templates, asking before each command in its default modes. safeguard exec runs the same flows in CI.

Safeguard does not read your service logs, audit your BMCs, evaluate your OpenStack policy files or re-encrypt images. Those steps stay with your operations team.

Zero-Day Discovery and Gold

Zero-Day Discovery looks for previously unknown flaws before a CVE exists, in an agentic mode and a deterministic scanner mode, across seven package ecosystems, and issues findings as SGZ advisories. Both Ironic and oslo.utils are published on PyPI. These issues did not come from Zero-Day Discovery and no Safeguard advisory existed for them; the Metal3 security team and a Red Hat engineer reported them through OpenStack's process. Gold Open Source at gold.safeguard.sh is free and shows affected and fixed versions, CVSS, EPSS, KEV status and a recommended safe version, and Gold Registry provides hardened, signed components. We are not claiming Gold has a fixed build of Ironic or oslo.utils for these issues. The habit that helps is the one in the next section: pull patched, signed components from a curated source, and rebuild fast once a fix exists. If you work through Python dependency audits more broadly, our post on auditing Python dependencies covers the basics, and the compromised dependency playbook covers what to do when a library you trust turns into the problem.

FAQ

Is any of this being exploited?

No exploitation has been reported in any source we checked on 24 October, and neither CVE was in the CISA KEV catalog (version 2026.10.23). Treat the Ironic bugs as normal priority fixes and the log exposure question as urgent if it applies to you.

Which Ironic version fixes CVE-2026-90458 and CVE-2026-89419?

Per the CVE records, 29.1.1, 32.1.1, 35.1.1 and 39.0.1 are the first fixed versions in their lines. None of them was released on 24 October. Until they are, use distribution packages that cite the CVEs or build from the stable branch commits listed above.

Which oslo.utils version fixes OSSN-0111?

10.3.0, according to the note. It was not on PyPI on 24 October; the newest release was 10.2.0. The fix is on master as commit 8d11103f2df4, with no stable branch backport proposed yet.

Is my LUKS passphrase compromised?

The note says the passphrase itself is not logged. What was logged is worse for that image: the master key candidate, which decrypts the image directly when the passphrase was correct. Changing the passphrase does not help. Re-encrypt with a new master key.

Does raising the log level remove key material already logged?

No. It only stops new lines being written. Search and clean existing logs, archives and backups, and re-encrypt any image whose key appeared.

Does 047 let an ordinary cloud user attack BMCs?

Not under default policy. The vendor passthru policy defaults to system scoped administrators. It matters because those administrators should not get arbitrary Redfish access to BMCs through Ironic, and because some deployments widen that policy or run Ironic standalone with simpler authentication.

What can a lessee member do with 048?

Set or clear a node's maintenance flag and reason through a generic node update, which default policy reserves for lessee admins and managers. The CVE record rates it 5.0 with high attack complexity. It does not grant broader control over the node.

We use Metal3 or OpenShift bare metal. What should we do?

Ask your platform vendor which Ironic commit their images carry and when the fixes for CVE-2026-90458 and CVE-2026-89419 will ship. Meanwhile, restrict who holds full Ironic API credentials and audit BMC accounts and subscriptions.

Fix it without waiting for upstream

For these three issues the gap is unusually visible: fixes are merged in git, but no release carries them yet. The same logic applies to every dependency you ship.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would have helped

These demos show general workflows, not this incident.

The first is a real CLI session fixing a lodash CVE: the assistant reads the finding, asks before each command, edits the manifest, runs install and tests, and pushes nothing. Here you would run it in the repository that builds your Ironic image and ask it to add the two cherry picks, or the default_log_levels line to your config templates, approving each step.

Click through it at your own pace, or open it full screen.

The second is a desktop app session: you ask for work on your computer, pick the folder, then Approve or Deny each command and file edit, ending with an upgrade done and tests passing. Here an operator could request the log level change across every service config in a deployment repository and review each edit.

Click through it at your own pace, or open it full screen.

The third sets up the local runner on your machine, approves it with a device code and scans from the terminal. Here you would scan each OpenStack service image to see which carry oslo.utils 10.1.0 to 10.2.0 or an unpatched Ironic.

Click through it at your own pace, or open it full screen.

You can download Safeguard and read the CLI documentation to try these flows on your own repositories. For other incidents from this month, see October 2026 security incidents and what would have helped.

Quick check

We upgraded oslo.utils to a fixed build. Are we done with OSSN-0111?

No. The upgrade only stops new key material being logged. If the inspector ran with a passphrase while DEBUG was on, search your logs, archives and backups, and re-encrypt any affected image with a new master key. Changing the passphrase is not enough.

Who can trigger OSSA-2026-048 under default Ironic policy?

A user with the member role in the project set as the node's lessee. The fix makes generic node updates that touch maintenance fields use the set_maintenance policy, which by default needs lessee admin or manager.

Sources

Last reviewed: 24 October 2026. This is a developing story; check the linked advisories for the latest status.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.