CVE-2026-45793 is a high-severity (CVSS 7.5) Information Exposure vulnerability in composer/composer. A fix is available for composer/composer — see the affected versions and patch details below.
Composer: Github Actions issued GITHUB_TOKEN disclosure in GitHub Actions logs
Exploitation Status
No confirmed exploitation observed yet
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-45793.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-45793 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 381,682 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
composer/composer🐘composer/composer🐘composer/composerReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
Summary
Composer leaks the full contents of tokens configured as GitHub OAuth tokens if they do not match Composer's expected format for such tokens to stderr. GitHub has introduced a new format for GitHub Actions GITHUB_TOKEN values. These tokens are validated in the same way by Composer on GitHub Actions. The new format including a - (hyphen) fails Composer's validation and leads to disclosure of the GITHUB_TOKEN in logs.
Many widely-used Actions (e.g. shivammathur/setup-php) auto-register GITHUB_TOKEN into composer's global auth.json, so the leak triggers without any unusual user configuration.
GitHub Actions tokens expire when the associated job finishes, and they are scoped to the respective repository only. So in most regular cases the Composer validation, which errors while leaking the token, also immediately ends the job, expiring the token immediately. Tokens expire at the very latest after 6 hours on GitHub-hosted runners. If you use self-hosted runner, expiration is at most 24 hours after creation. The new token format is being rolled out gradually, so not all repositories are affected yet, but will be soon.
Classic ghp_ PATs are not affected by the regex bug per se, but the same leak primitive applies to any future credential that fails validation for any reason.
Details
When a GitHub token fails regular expression validation of the character set, the rejected token is interpolated verbatim into the UnexpectedValueException message thrown by Composer\IO\BaseIO::loadConfiguration(), which Symfony Console then prints. Validation reliably fails for any token containing a - (hyphen), which includes the modern ghs_<id>_<base64url-JWT> GitHub App installation token format, the same format used by GitHub Actions' built-in GITHUB_TOKEN and by actions/create-github-app-token.
Severity: medium. Pre-conditions are common in real-world CI. Practical blast radius is bounded by the leaked credential's scope and TTL (short for a workflow GITHUB_TOKEN, longer for App-minted tokens or user-issued credentials that happen to contain -).
Vulnerable code, src/Composer/IO/BaseIO.php (line 139 on main, line 143 on 2.8.x), inside loadConfiguration():
// allowed chars for GH tokens are from https://github.blog/changelog/2021-03-04-authentication-token-format-updates/
// plus dots which were at some point used for GH app integration tokens
if (!Preg::isMatch('{^[.A-Za-z0-9_]+$}', $token)) {
throw new \UnexpectedValueException(
'Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"'
);
}
Three issues combine to produce the leak:
-
The rejected token is interpolated into the exception message. The exception bubbles up to Symfony Console's default error renderer, which writes it to stderr. Any environment that captures stderr (CI logs, log shippers, monitoring, support transcripts) now has the raw token.
-
The validation regex
^[.A-Za-z0-9_]+$does not permit-. GitHub's currentghs_<numeric-id>_<base64url-JWT>structured installation tokens routinely contain-, because base64url (RFC 4648 §5) uses-and_as URL-safe replacements for+and/. The regex was chosen in 2021 on the understanding that GitHub tokens use only[A-Za-z0-9_]plus.. -
Detection / mitigation in upstream platforms is unreliable. GitHub Actions' built-in secret masker matches registered values as exact substrings. When the exception message is rendered by Symfony Console it may wrap, embed in
In BaseIO.php line N:framing, or interleave with ANSI control sequences. So the masker does not redact, and the plaintext token reaches the log.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | composer/composer | ≥ 2.3.0&&< 2.9.8 | 2.9.8composer require composer/composer:^2.9.8 |
| 🐘Packagist | composer/composer | ≥ 2.0.0&&< 2.2.28 | 2.2.28composer require composer/composer:^2.2.28 |
| 🐘Packagist | composer/composer | ≥ 1.0&&< 1.10.28 | 1.10.28composer require composer/composer:^1.10.28 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for composer/composer, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update composer/composer to 2.9.8 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-45793 is resolved across your whole dependency graph.
Workarounds
Assume what was exposed is already known: rotate any credential, token or key that the affected component could return, restrict the endpoint to callers that genuinely need it, and strip sensitive fields from responses and error output at the boundary rather than relying on the client not to read them.
Frequently Asked Questions
Is CVE-2026-45793 in your dependencies?
Find it across Packagist, including transitive dependencies.