CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-QHH4-458H-XWH2
5.3

GHSA-qhh4-458h-xwh2: Credential Leakage via Origin Validation Error in cdxgen

Alon Barad
Alon Barad
Software Engineer

May 8, 2026·9 min read·5 visits

PoC Available

Executive Summary (TL;DR)

Versions 9.9.5 through 12.3.2 of @cyclonedx/cdxgen leak Docker registry credentials due to an insecure substring matching implementation. Upgrading to version 12.3.3 resolves the vulnerability by introducing strict hostname normalization.

The @cyclonedx/cdxgen package is vulnerable to credential leakage due to improper Docker registry origin validation. A flaw in how registry authentication endpoints are matched against configured credentials allows arbitrary downstream registries to capture private credentials.

Vulnerability Overview

The @cyclonedx/cdxgen package operates as a software bill of materials (SBOM) generation tool, widely integrated into automated Continuous Integration and Continuous Deployment (CI/CD) pipelines. To construct an accurate SBOM for containerized applications, the tool must frequently interact with container registries to pull image manifests and layer metadata. This operation requires the software to handle sensitive authentication credentials, specifically those utilized by the local Docker daemon for private registry access.

The vulnerability, identified as GHSA-qhh4-458h-xwh2, exists within the credential resolution mechanism of the application. It affects all versions from 9.9.5 up to, but excluding, 12.3.3. When the tool processes a request to scan a remote container image, it attempts to attach the appropriate authentication headers to the Docker API request. The flaw lies in the algorithm used to select these headers from the local configuration state.

This security defect is classified under two Common Weakness Enumeration identifiers: CWE-346 (Origin Validation Error) and CWE-522 (Insufficiently Protected Credentials). The application fails to properly validate the origin of the requested registry against the configured registry endpoints. This architectural failure leads directly to the exposure of private credentials to unintended third parties.

The primary risk surfaces in automated environments that process untrusted or externally supplied image references. A system executing cdxgen against an arbitrary image repository could unknowingly transmit highly privileged tokens intended for internal registries. The exposure of these credentials compromises the integrity and confidentiality of the organization's private container infrastructure.

Root Cause Analysis

The vulnerability originates in the module responsible for interfacing with the local Docker daemon, specifically within lib/managers/docker.js. When the application initiates an image scan, it must authenticate with remote registries to fetch image layers and manifests. To accomplish this, the software parses the local Docker configuration file, typically located at ~/.docker/config.json.

This configuration file stores authentication metadata as a JSON object, where the keys are the registry server addresses and the values are base64-encoded authentication strings. The parsing logic iterates through these keys to locate the appropriate credentials for the specific registry hosting the target image. The fundamental error occurs during this selection process, where the application determines if a stored credential matches the target endpoint.

Instead of parsing the Uniform Resource Identifiers (URIs) to extract and compare the precise hostnames, the developers implemented a naive string inclusion check. The vulnerable conditional statement, if (forRegistry && !serverAddress.includes(forRegistry)), evaluates whether the target registry string exists anywhere within the stored server address string. This approach fundamentally violates origin validation principles by treating distinct hierarchical domains as equivalent if one forms a substring of the other.

Because domain names resolve hierarchically, a substring match does not guarantee domain control or equivalence. A target registry named registry.example.com will successfully trigger the .includes() condition against a stored credential for private-registry.example.com. The application fails to recognize that these domains represent entirely separate network entities, leading to the extraction and misuse of the private authentication token.

Architecture and Protocol Flow

Understanding the vulnerability requires analyzing the communication protocol between the cdxgen process, the local Docker daemon, and the remote container registry. The cdxgen utility does not pull the images directly over the network; instead, it delegates this operation to the Docker Engine via the Docker Engine API, typically accessed through a local Unix socket (/var/run/docker.sock).

To instruct the Docker daemon to pull an image from a private registry, the client must supply the credentials within the API request. The Docker Engine API specification dictates that credentials must be passed via the X-Registry-Auth HTTP header. The value of this header is a base64-encoded JSON object containing the username, password, and optionally the server address.

The vulnerability is isolated entirely within the client-side preparation of the X-Registry-Auth header. The cdxgen process improperly constructs this header using credentials that do not correspond to the requested destination. The Docker daemon acts as a confused deputy in this transaction.

The Docker daemon receives the valid, structurally correct API request and dutifully forwards the provided credentials to the target registry specified in the pull command. The daemon performs no secondary validation to ensure the provided credentials semantically match the target registry, assuming the client application has already performed the necessary authorization checks.

Code Analysis and Patch Review

The remediation, implemented in pull request 3964 (commit b1e179869fd7c6032c3d483c3f7bd4d7154ec22b), systematically replaces the flawed string comparison logic with strict structural evaluation. The patch modifies lib/managers/docker.js to eliminate the usage of String.prototype.includes() for origin validation.

The vulnerable implementation relied on a direct conditional bypass:

// Pre-patch vulnerable logic
for (const serverAddress of Object.keys(dockerConfig.auths)) {
  if (forRegistry && !serverAddress.includes(forRegistry)) {
    continue;
  }
  // ... credential extraction logic
}

The patched version introduces two new validation functions: normalizeRegistryHost() and registriesMatch(). The normalizeRegistryHost() function sanitizes the input by removing protocol schemes (e.g., https://), trailing slashes, and port numbers. This ensures that the application compares only the core hostname components.

The new validation routine executes a strict equality check (===) between the normalized configuration key and the normalized target registry.

// Post-patch secure logic
for (const serverAddress of Object.keys(dockerConfig.auths)) {
  if (forRegistry && !registriesMatch(serverAddress, forRegistry)) {
    continue;
  }
  // ... credential extraction logic
}

Additionally, the patch includes specific handling for Docker Hub aliases. Because Docker Hub can be referenced via multiple endpoints (docker.io, index.docker.io, registry-1.docker.io), the registriesMatch() function contains hardcoded logic to treat these specific domains as equivalent. This ensures backward compatibility and proper functionality without compromising the strict equivalence requirements for arbitrary third-party domains.

Exploitation Methodology

Exploiting this credential leakage vulnerability requires the attacker to influence the image reference parsed by the victim's cdxgen installation. The execution context typically involves a CI/CD pipeline configured to automatically generate SBOMs for dependencies, pull requests, or external manifests.

The initial step for the attacker involves reconnaissance to identify the domain name of the target organization's internal container registry. If the victim utilizes a registry at corp-internal-registry.com, the attacker must register a domain that functions as a substring, such as registry.com, assuming the Top-Level Domain and availability permit. Alternatively, the attacker can leverage subdomains if the configuration matches against higher-level paths.

Once the requisite infrastructure is established, the attacker submits a modified manifest, repository configuration, or direct command line argument containing a reference to an image hosted on their controlled domain. When the pipeline executes cdxgen against this reference, the application queries the local configuration for credentials.

The substring evaluation succeeds, and the application generates an X-Registry-Auth header containing the base64-encoded credentials for corp-internal-registry.com. The attacker's registry receives the inbound HTTP request. The attacker merely needs to inspect the HTTP headers, extract the X-Registry-Auth value, and decode the base64 string to obtain the plaintext username and password.

Impact Assessment

The CVSS v4.0 vector for this vulnerability is CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:L/SA:N, resulting in a base score of 5.3 (Medium). This vector accurately reflects the specific conditions and consequences of the vulnerability. The attack vector is Network (AV:N) as the leakage occurs over outbound HTTP requests, and no specialized access conditions (AC:L) are required beyond standard network connectivity.

Privileges Required (PR:N) and User Interaction (UI:N) are evaluated as None because the vulnerability triggers automatically during the routine execution of the tool, commonly within automated, unattended pipelines. The attacker does not need prior authentication to the victim's infrastructure, nor do they require a human to manually approve the credential transmission.

The primary impact is to Confidentiality (VC:L). The designation is Low rather than High because the vulnerability does not provide arbitrary memory read capabilities or total system compromise; it selectively leaks a specific set of credentials. However, the operational consequence of this leakage is substantial, as these credentials often provide access to proprietary source code and internal intellectual property.

The Subsequent System Integrity (SI:L) reflects the risk that an attacker, armed with the stolen credentials, could push malicious images or modify existing containers within the victim's private registry. This establishes a vector for severe supply chain attacks, though the vulnerability itself only facilitates the initial credential theft.

Remediation and Mitigation

The definitive remediation for this vulnerability requires updating the @cyclonedx/cdxgen package to version 12.3.3 or higher. Administrators must identify all environments where the tool is deployed, including developer workstations, dedicated build servers, and ephemeral CI/CD container images. The update process involves executing npm install -g @cyclonedx/cdxgen@latest for global installations.

Organizations should assume that long-lived credentials utilized in automated environments may have been exposed if the pipeline previously processed untrusted external dependencies. Security teams must initiate standard credential rotation procedures for all Docker registry service accounts associated with infrastructure running the vulnerable software versions.

Network-level egress filtering serves as a critical defense-in-depth mitigation. CI/CD pipelines responsible for building and scanning internal software should operate within environments restricted from making arbitrary outbound network connections. By configuring firewalls or proxies to allow traffic exclusively to explicit, verified endpoints (e.g., specific internal registries or authorized public repositories), organizations prevent the exfiltration of credentials regardless of application-layer flaws.

Finally, development teams should transition from static configuration files (config.json) to dynamic, short-lived authentication tokens managed by explicit environment variables or secure secret management systems. The patched version of cdxgen prioritizes environment variables (DOCKER_AUTH_CONFIG, DOCKER_USER) over configuration files, enabling more granular and secure credential injection mechanisms.

Official Patches

CycloneDXFix pull request introducing strict host matching.

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:L/SA:N

Affected Systems

macOS / Linux / Windows running Node.js and @cyclonedx/cdxgen < 12.3.3CI/CD pipelines utilizing vulnerable versions for SBOM generationDocker Daemon instances invoked by vulnerable cdxgen processes

Affected Versions Detail

Product
Affected Versions
Fixed Version
@cyclonedx/cdxgen
CycloneDX
>= 9.9.5, < 12.3.312.3.3
AttributeDetail
CWE IDCWE-346, CWE-522
Attack VectorNetwork
CVSS v4.05.3 (Medium)
ImpactCredential Leakage
Exploit StatusProof of Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1552Unsecured Credentials
Credential Access
T1190Exploit Public-Facing Application
Initial Access
CWE-346
Origin Validation Error

The software does not properly verify the origin of data or requests, allowing unauthorized data access or leakage.

Vulnerability Timeline

GitHub Advisory Published
2025-05-08
Patch released in version 12.3.3
2025-05-01

References & Sources

  • [1]GitHub Advisory: GHSA-qhh4-458h-xwh2
  • [2]Official Repository
  • [3]Fix Pull Request
  • [4]OSV Advisory

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.