惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 【当耐特】
A
About on SuperTechFans
Last Week in AI
Last Week in AI
雷峰网
雷峰网
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
博客园 - 叶小钗
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
The Cloudflare Blog
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements

Sansec - experts in eCommerce security

GorgonAgora: 4,800+ fake storefronts skim cards across hundreds of impersonated brands Sansec adds support for Sylius 1 & 2 Critical vulnerability in Mirasvit Cache Warmer for Magento Critical FunnelKit vulnerability threatens 40,000+ WooCommerce checkouts Over 200 PrestaShop stores expose installer, allowing full takeover ClickFix malware hits DoD cybersecurity vendor homepage SVG Onload Tag Hides Magecart Skimmer on 99 Stores Mass PolyShell attack wave hits 471 stores in one hour Novel WebRTC skimmer bypasses security controls at $100+ billion car maker PolyShell: unrestricted file upload in Magento and Adobe Commerce Digital skimmer hits global supermarket chain Building a faster YARA engine in pure Go Magento Developers Impersonated in Targeted GitHub Malware Operation Claude finds 353 zero-days on Packagist The billion-dollar security.txt problem Keylogger targets 200,000+ employees at major US bank ConnectPOS leaked Github secrets for years Critical backdoor found in MGT Varnish extension SessionReaper attacks have started, 3 in 5 stores still vulnerable SessionReaper, unauthenticated RCE in Magento & Adobe Commerce (CVE-2025-54236) Adobe patches critical Magento admin takeover via menu injection Backdoor found in popular ecommerce components Found defunct.dat on your site? You've got a problem. You have 2 weeks left to set up CSP for your store Merchants left guessing at last-minute PCI-DSS u-turn Magento Security Release APSB25-08 [Impact Analysis] Sorry, client-side security does not work Google services abused in skimming campaigns Thousands of Adobe Commerce stores hacked in competing CosmicSting campaigns CosmicSting attack & defense overview
Composer vulnerability leaks GitHub tokens, threatens PHP...
Sansec Forensics Team · 2026-05-13 · via Sansec - experts in eCommerce security

Update May 13th: GitHub has temporarily rolled back the new token format rollout. According to the Composer maintainers, that leaves a few days to update Composer in CI before the rollout resumes next week.

Composer maintainers released emergency patches today for a vulnerability that prints raw GitHub tokens into CI job logs. The fix ships in 2.9.8, 2.2.28 (LTS), and 1.10.28 (legacy). Every PHP CI pipeline running an older Composer with shivammathur/setup-php (or any action that auto-registers GITHUB_TOKEN) is exposed.

The leaked credential is the GITHUB_TOKEN from whatever workflow ran Composer. For workflows triggered by push, schedule, or pull_request_target, that token may have write access to the source repository, depending on the repository's default permissions.

How the leak works

Composer validates GitHub OAuth tokens loaded from auth.json against a regex. The regex was added in 2021 and accepts only the characters [.A-Za-z0-9_]. GitHub's token formats at the time contained no hyphens, so every valid token passed.

GitHub later rolled out a new structured token format for GitHub Actions: ghs_<id>_<JWT>. The announcement stated:

This should not impact your existing Actions workflows.

The JWT segment is base64url-encoded, which often includes hyphens. The new tokens fail Composer's regex on the first hyphen they contain.

When validation fails, Composer interpolates the raw token directly into the exception message:

if (!Preg::isMatch('{^[.A-Za-z0-9_]+$}', $token)) {
    throw new \UnexpectedValueException(
        'Your github oauth token for '.$domain.
        ' contains invalid characters: "'.$token.'"'
    );
}

Symfony Console renders the unhandled exception to stderr, dropping the full token into the CI job log.

In CI, the common entry point is shivammathur/setup-php, used by tens of thousands of public workflows. The action writes GITHUB_TOKEN into Composer's global auth.json with no opt-in required, so the next composer invocation triggers the failed validation and dumps the token.

Why GitHub's secret masking failed

GitHub Actions scans each log line for the registered secret bytes and replaces matches with ***. The matcher only catches contiguous copies of the token.

Symfony Console's exception renderer interleaves ANSI color escape sequences through the output and wraps long lines at the terminal width, so the token never appears contiguously in a single write. In archived runs the boxed ##[error] annotation shows ***, while the raw stderr line directly below it prints the token in full.

What the token can do

The leaked token's permissions depend on the repository's GITHUB_TOKEN default. GitHub flipped that default to read-only on February 2, 2023, but only for newly created organizations and personal-account repositories. The announcement is explicit:

This change will not impact any existing enterprises, organizations or repositories.

Any project predating the change continues to issue read/write tokens unless an admin has manually tightened the setting.

Exposure window

GitHub's documentation states the GITHUB_TOKEN "expires when the job finishes or after its effective maximum lifetime." The Composer security advisory repeats the claim, describing tokens that "expire when the job ends."

The leaked credential is a JWT with a 1-hour signed expiry. Once the job completes, GitHub revokes write-scoped tokens within seconds. Sansec and the original researcher independently verified that this revocation can often be raced: a token harvested while the job is still in_progress is accepted by GitHub's API. In Sansec's testing, a window of under 2 seconds was enough to capture the token and push a commit. For workflows that do other work after Composer (test, build, deploy), that window can be minutes.

Why this matters for the PHP supply chain

Composer pulls dependencies from Packagist, which mirrors releases from GitHub repositories. A maintainer who publishes a popular library typically has a CI workflow that runs Composer on every push, and a scheduled workflow that runs nightly. If those workflows use shivammathur/setup-php, the maintainer's GITHUB_TOKEN lands in the job log.

For a public repository, the log is public. An attacker who harvests a write-scoped token from a push or schedule run on a widely depended-on library can push a malicious commit and tag a release. Downstream CI pipelines running composer update pull the compromised code within minutes.

Recommendations

  1. Update Composer: do not pin a specific Composer version in your CI workflows. shivammathur/setup-php installs the latest stable Composer by default, which now contains the fix and will pick up future patches automatically.

  2. Drop default token permissions to read-only: at the organization or repository level, set the default GITHUB_TOKEN permission to read. Grant write only where the workflow needs it. This neutralizes the leak for every workflow that does not need to push.

  3. Freeze dependencies: avoid pulling new package versions until the broader impact is assessed.

Timeline

DateEvent
2021Token validation regex added to Composer (excludes hyphen)
May 12, 2026Damien Retzinger discovers the leak during incident triage
May 12, 2026Reported privately to Composer maintainers and GitHub PSIRT
May 12, 2026Reported as a public issue by GitHub user kesselb
May 13, 2026Composer 2.9.8, 2.2.28, and 1.10.28 released. GHSA-f9f8-rm49-7jv2 published
May 13, 2026Sansec publishes this advisory
May 13, 2026GitHub temporarily rolls back the new token format

Read more