Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59947

CVE-2026-59947: Composer Information Disclosure Flaw

CVE-2026-59947 is an information disclosure vulnerability in Composer that exposes credentials in debug output when run with verbose flags. This article covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-59947 Overview

CVE-2026-59947 is an information disclosure vulnerability in Composer, the widely used dependency manager for PHP. When Composer runs with the -vvv debug verbosity flag, it can print credentials embedded in the username slot of a repository or package URL to debug output. This affects URLs of the form https://TOKEN@host/, such as those containing a GitHub Personal Access Token. The AuthHelper, Url::sanitize, and ProcessExecutor components did not sanitize username-only URL credentials before logging them. The issue is fixed in Composer versions 2.2.29 and 2.10.2.

Critical Impact

Sensitive authentication tokens embedded in repository URLs may be written to debug logs, CI/CD build output, or terminals, exposing them to anyone with read access to those logs.

Affected Products

  • Composer versions prior to 2.2.29 (2.2.x branch)
  • Composer versions prior to 2.10.2 (2.x branch)
  • PHP projects and CI/CD pipelines that invoke Composer with -vvv verbosity

Discovery Timeline

  • 2026-07-08 - CVE-2026-59947 published to NVD
  • 2026-07-08 - Last updated in NVD database

Technical Details for CVE-2026-59947

Vulnerability Analysis

Composer supports authenticated repository access using URL-embedded credentials. Users can supply a token or username-only credential as https://TOKEN@host/path. When run with maximum verbosity (-vvv), Composer emits detailed debug output that includes URLs and authentication display messages.

The sanitization routines AuthHelper, Url::sanitize, and ProcessExecutor masked the user:password form but did not strip credentials placed only in the username slot. As a result, a GitHub Personal Access Token, GitLab CI token, or similar secret embedded as the URL username was written to debug output verbatim. This condition is classified as insertion of sensitive information into log files [CWE-532].

Root Cause

The sanitization logic assumed credentials always appear as username:password pairs. Username-only URL credentials, common for bearer-style tokens, bypassed the masking checks in Url::sanitize() and were echoed in the AuthHelper display message that reports the authentication method being used.

Attack Vector

Exploitation requires local access to Composer output, log files, or CI/CD build artifacts. An attacker who reads debug logs from a shared build system, an unprotected CI job, or a compromised developer workstation can extract the leaked token and reuse it against the target repository host. No network attack vector or user interaction is required beyond obtaining log access.

php
// Patch: src/Composer/Util/AuthHelper.php
// The display message now routes the username through Url::sanitizeUsername()
// before being printed to debug output.

} else {
    $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
    $headers[] = 'Authorization: Basic '.$authStr;
-   $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"';
+   $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . Url::sanitizeUsername((string) $auth['username']) . '"';
}

if ($authenticationDisplayMessage && (!isset($this->displayedOriginAuthentications[$origin]) || $this->displayedOriginAuthentications[$origin] !== $authenticationDisplayMessage)) {

Source: Composer commit 6bd66874

php
// Patch: src/Composer/Util/Git.php
// The hard-coded list of non-secret credential names is replaced with the
// centralized Url::NON_SECRET_CREDENTIALS constant so masking stays consistent.

$maskedCredentials = array();

foreach ($credentials as $credential) {
-   if (in_array($credential, array('private-token', 'x-token-auth', 'oauth2', 'gitlab-ci-token', 'x-oauth-basic'))) {
+   if (in_array($credential, Url::NON_SECRET_CREDENTIALS, true)) {
        $maskedCredentials[] = $credential;
    } elseif (strlen($credential) > 6) {
        $maskedCredentials[] = substr($credential, 0, 3) . '...' . substr($credential, -3);

Source: Composer commit 8887ad76

Detection Methods for CVE-2026-59947

Indicators of Compromise

  • Composer debug output containing strings such as Using HTTP basic authentication with username "ghp_..." or other token-shaped values in the username field.
  • CI/CD job logs referencing repository URLs in the form https://<token>@github.com/ or https://<token>@gitlab.com/.
  • Build artifacts, cached console output, or archived pipeline logs containing high-entropy strings adjacent to Composer verbosity banners.

Detection Strategies

  • Scan CI/CD log archives and developer workstation shell histories for Composer invocations that combine composer with -vvv and URLs containing an @ in the authority component.
  • Grep repository URLs and log stores for known token prefixes (for example ghp_, github_pat_, glpat-) appearing before an @ character.
  • Audit installed Composer versions across build agents and developer laptops using composer --version and compare against fixed releases 2.2.29 and 2.10.2.

Monitoring Recommendations

  • Enable secret-scanning on internal log aggregation systems and Git repositories to catch tokens leaked by past debug runs.
  • Alert on Composer processes launched with -vvv or --verbose --verbose --verbose in production or shared CI runners where debug verbosity should not be routine.
  • Track PAT and CI token usage server-side (GitHub, GitLab, private registries) for anomalous source IPs or user agents that could indicate reuse of an exposed token.

How to Mitigate CVE-2026-59947

Immediate Actions Required

  • Upgrade Composer to 2.2.29 on the 2.2.x LTS branch or to 2.10.2 on the current branch across all developer machines, container images, and CI/CD runners.
  • Rotate any GitHub Personal Access Tokens, GitLab CI tokens, or private registry credentials that were ever embedded in a repository URL passed to Composer with debug verbosity enabled.
  • Purge historical CI/CD logs, build artifacts, and cached console output that may contain leaked tokens, or restrict their access to a minimal audience.

Patch Information

The maintainers released fixes in Composer 2.2.29 and Composer 2.10.2. Technical details are documented in GitHub Security Advisory GHSA-g6xq-892h-64w3. The fixes introduce Url::sanitizeUsername() and centralize non-secret credential names in Url::NON_SECRET_CREDENTIALS, ensuring AuthHelper, Url::sanitize, and ProcessExecutor mask username-only credentials before writing them to output.

Workarounds

  • Avoid running Composer with -vvv in shared environments or CI/CD pipelines until the upgrade is applied.
  • Migrate away from URL-embedded credentials by using composer config to store authentication in auth.json or the COMPOSER_AUTH environment variable, which are not printed in debug output.
  • Restrict access to Composer log output and CI artifacts on a least-privilege basis while remediation is in progress.
bash
# Upgrade Composer to a fixed release
composer self-update 2.10.2
# or, for the 2.2 LTS branch
composer self-update 2.2.29

# Move credentials out of URLs and into auth.json
composer config --global --auth github-oauth.github.com <NEW_TOKEN>
composer config --global --auth gitlab-token.gitlab.com <NEW_TOKEN>

# Verify the installed version
composer --version

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.