A Composer Bug Was Leaking GitHub Tokens Into Your CI Logs. Here's How to Check
I run Composer inside GitHub Actions for most of my Laravel deploys, the same way a lot of small teams do. So when I read that a Composer bug had been leaking GitHub tokens straight into CI logs, I stopped what I was doing and went to check my own workflows. If you deploy PHP through GitHub Actions too, this is worth ten minutes of your time.
What actually happened
GitHub started rolling out a new format for its Actions tokens in April 2026. The new format could include a hyphen. Composer's own validation code had never been built to expect that character in a token, so when it received one of these new-format tokens, it rejected it, and printed the full rejected value into its error output. GitHub Actions then captured that error output and stored it in the job log, exactly where anyone with access to the workflow run could see it. This is tracked as CVE-2026-45793. It's not a theoretical bug. If your CI ran during the rollout window with the new token format, and Composer choked on it, your token may have sat in plain text in a log file that anyone with repo access could open.
Check if you were affected
Start with your Composer version, since this tells you whether you were ever exposed to the bug at all:
composer --version
Versions before 2.9.8, and before 2.2.28 on the LTS line, contain the bug. If you're already past those, you're clear on this specific issue, though it's still worth reading on, since older cached Composer binaries in Docker images are a common way this lingers longer than people expect.
Next, look through your recent GitHub Actions run history for any job that failed on a Composer step around April or May 2026. Open the raw logs for those runs and search for anything that looks like a token, typically a long string starting with ghs_ or ghp_. If you find one, treat it as compromised.
The fix
Update Composer first:
composer self-update
That pulls the latest 2.x release, which includes the fix. If you're specifically pinned to the 2.2 LTS line for PHP compatibility reasons, target that line directly instead:
composer self-update --2.2
Updating stops it from happening again. It does nothing about a token that's already sitting in an old log file, so that part needs a manual check on your side.
If you found an exposed token
Revoke it and issue a new one. For a GitHub App installation token, this usually means going into your app's settings and reinstalling, or reviewing the app's permissions and forcing a token refresh. For a standard GITHUB_TOKEN, these expire automatically at the end of each workflow run, so the exposure window is smaller by design, but I'd still treat any repo the token had write access to as worth a second look for anything unexpected in that timeframe.
Why this matters even if you weren't hit directly
If you're building your own Docker images for deployment, the way we've talked about in our multi-app VPS guide, it's easy for an old Composer binary to sit baked into a base image for months without anyone thinking to update it. A Dockerfile that installs Composer once and gets rebuilt from cache repeatedly can quietly carry a vulnerable version long after everyone else has moved on. Worth adding a line to actually check the version as part of your build, rather than assuming a base image is current just because it was pulled recently.
RUN composer --version
A visible version number in your build logs costs nothing and makes this kind of check a lot faster next time something like this comes up, and something like this will come up again.
I verified the CVE details and fixed versions in this guide against Packagist's own official security update as of August 2026.
Comments 0
Be the first to comment.
Leave a comment