How a 90-Minute Git Tag Hijack Turned composer install Into a Credential Stealer
On May 22, 2026 at approximately 22:32 UTC, an attacker with push access to the Laravel-Lang GitHub organization rewrote every git tag across four widely used Composer packages: laravel-lang/lang, laravel-lang/http-statuses, laravel-lang/attributes, and laravel-lang/actions. The attack window lasted roughly 90 minutes, closing around 00:00 UTC on May 23 after GitHub removed the attacker-controlled fork commits and tags were restored.
Rather than publishing a new malicious version, the attacker redirected all existing tags to commits in an attacker-controlled fork. This exploited a fundamental property of Packagist's GitHub integration: the registry resolves version tags by following the git ref, not a pinned commit hash. Any team running composer install against these packages during the window received malicious code with no indication of a version change. laravel-lang/lang alone had 502 tags rewritten. Approximately 233 versions were tampered across three repositories, with Socket reporting up to 700 historical versions potentially affected (BleepingComputer, StepSecurity, Socket, Snyk).
The injected payload was embedded in helpers.php and wired into Composer's autoload.files manifest. Every composer install or composer update executed during the attack window ran this file automatically. No user prompt. No permission request. No artifact visible in most CI/CD logging configurations.
The payload is a cross-platform credential stealer targeting Linux, macOS, and Windows. It harvested cloud provider keys for AWS, GCP, and Azure; Kubernetes and Vault secrets; CI/CD tokens; SSH key material; browser-stored credentials; cryptocurrency wallet data; and .env files. All collected data was exfiltrated over HTTPS to an attacker-controlled endpoint. StepSecurity confirmed end-to-end exploitation in an isolated runner environment. No CVEs were assigned. This was a source repository compromise, not a code-level vulnerability.
The Detection Gap
Most blue teams have no visibility into what package managers install during CI/CD builds. Pipelines execute composer install silently, and the typical detection stack watches for network anomalies and known-bad process names but misses the semantics of package integrity and git tag mutation. Three detection gaps enabled this attack to succeed broadly.
No integrity verification on resolved commits. Composer's lockfile records a reference hash, but few teams continuously verify that hash against what the upstream repository is actually serving. A tag pointing to a different commit than it did the day before is invisible to teams not running continuous lockfile integrity checks.
No outbound network monitoring from ephemeral CI/CD runners. The payload exfiltrated credentials over HTTPS to an unknown endpoint. Teams with east-west visibility inside cloud environments often have no equivalent coverage on outbound traffic from ephemeral GitHub Actions or GitLab CI runners.
No alerting on autoload.files mutations. The autoload.files mechanism in Composer is legitimate but rarely used by language-pack libraries. A detection rule triggering on new entries added to autoload.files in a lockfile diff would have flagged this before execution.
Operationalizing a Response
For any team that ran composer install or composer update against these packages between May 22 22:32 UTC and May 23 00:00 UTC, credential rotation is the immediate priority. Package cleanup is secondary.
MITRE ATT&CK mapping:
- T1195.002 (Supply Chain Compromise: Compromise Software Dependencies): Initial access via git tag rewrite redirecting installs to attacker-controlled commits.
- T1059 (Command and Scripting Interpreter): The PHP
autoload.filesmechanism ran the credential stealer automatically at install time, requiring no user interaction. - T1552.001 (Unsecured Credentials: Credentials In Files): Payload targeted
.envfiles, cloud credential files, and SSH key material on the runner filesystem. - T1041 (Exfiltration Over C2 Channel): Collected data exfiltrated over HTTPS to an attacker-controlled endpoint.
Detection and response playbook:
- Audit CI/CD execution logs for any
composer installorcomposer updateruns between May 22 22:32 UTC and May 23 00:00 UTC. Identify which packages were resolved and from which commit SHAs. - Pull
composer.lockfiles from affected pipeline runs. Compare the recorded commit SHA for each laravel-lang package against the current HEAD of the official laravel-lang GitHub repositories. A mismatch confirms consumption of a malicious commit. - Rotate all credentials accessible from affected build environments: AWS IAM keys, GCP service account keys, Azure service principals, CI/CD platform tokens, Vault tokens, SSH keys, and any secrets mounted as environment variables or files in the runner.
- Query VPC flow logs or your SIEM for outbound HTTPS connections from affected runners to unknown endpoints during the attack window. Flag any connections to destinations outside your approved network baseline.
- For forward hardening: pin Composer dependencies to verified commit SHAs in
composer.lock. Require--no-pluginson installs in isolated CI/CD environments. Run Composer inside a network-isolated container with egress restricted to known package registries.
How BlueTeamAutomation Covers This Class of Threat
Supply-chain attacks succeed because blue teams lack continuous coverage across the delivery pipeline, the build environment, and the credential plane simultaneously. A one-time audit finds nothing. The Laravel-Lang attack was complete in 90 minutes, well inside any manual review cycle.
Continuous BAS validation ensures your detection rules for supply-chain TTPs are exercised before an attacker does it for real. BASzy, our breach and attack simulation engine, runs simulations mapped to T1195.002 and T1041 against your pipelines and confirms that your detection and response controls actually fire before a live event exposes the gap. A one-time audit finds nothing; a continuous validation loop finds the holes while you still have time to close them.
Find the exposure before it's exploited. CVEasy, our local-first CTEM platform, gives you continuous visibility into vulnerable and outdated dependencies across your environment. Its TRIS v2 scoring prioritizes which package-integrity and dependency risks matter most to your specific stack, so a small team patches the exploitable issues first instead of chasing CVSS noise. Because it runs on your hardware, your source and dependency manifests never leave your control.
Close the loop. Pair BASzy validation with CVEasy exposure management and you cover both sides of supply-chain defense: know which dependencies put you at risk, and prove your detections would catch an attacker who weaponizes them. When your auditor asks whether you detected and responded to a Laravel-Lang class event, you point to validated detection coverage and a current exposure inventory rather than reconstructing logs under deadline pressure.
For MSSPs managing PHP development teams across multiple customers, this coverage scales from a single console: validate detection with BASzy, manage exposure with CVEasy, and lean on our security services team for incident response and credential rotation when a real event lands. The full blue-team workflow stays auditable from detection through remediation.
Automate your supply-chain defense
Validate your detections with BASzy and manage your dependency exposure with CVEasy. Talk to us about covering the full supply-chain workflow.
Get a Walkthrough →