Skip to main content

On 22 May 2026, an attacker with push access to the Laravel-Lang GitHub organisation rewrote every git tag across four popular Composer packages in a single fifteen-minute window. No malicious code was ever committed to the official repositories. Instead, the attacker exploited a little-known GitHub feature — version tags can reference commits inside forks of the same repository — to redirect legitimate-looking release tags to a malicious fork they controlled. The result: anyone running composer update or a fresh composer install against those packages pulled a cross-platform credential stealer that auto-executed on every PHP request.

If your team ships PHP, this is not optional reading.

TL;DR

  • Four Laravel-Lang Composer packages (laravel-lang/lang, http-statuses, attributes, actions) had 700+ historical versions poisoned via git tag rewriting on 22 May 2026
  • The attack vector was novel: GitHub allows tags to point at fork commits, so no malicious code ever touched the official repositories
  • A malicious src/helpers.php registered under autoload.files in composer.json executed automatically on every PHP request, exfiltrating CI/CD tokens, cloud credentials, SSH keys, .env files, and browser data
  • If you ran composer update or composer install on or after 22 May 2026 22:32 UTC for any of these packages, treat every secret in that environment as compromised
  • Composer lockfile hygiene, tag signature verification, and network egress controls are your primary defences

The Attack: Git Tags as a Weapon

Supply chain attacks on package managers are nothing new. We have covered TanStack’s GitHub Actions compromise and npm typosquatting campaigns on this blog before. But the Laravel-Lang attack introduces a genuinely novel vector that deserves attention from every team managing PHP dependencies.

Here is how it worked:

  1. Fork the target repository. The attacker forked the official Laravel-Lang repos — an action available to anyone on GitHub.
  2. Add a malicious commit to the fork. A file called src/helpers.php was added containing a cross-platform credential stealer. This file was registered in composer.json under autoload.files, ensuring it runs automatically — no manual include required.
  3. Rewrite every tag in the official repo. Using push access to the Laravel-Lang organisation, the attacker deleted and recreated every existing git tag so that each pointed at the malicious commit in the fork instead of the original, legitimate commit.
  4. Sit back. Any CI/CD pipeline, developer workstation, or production server that ran composer update or composer install without a locked, verified lockfile now pulled the poisoned code.

The entire operation took roughly fifteen minutes. More than 700 versions across four packages were compromised before anyone noticed.

What the Payload Steals

The malicious helpers.php file is not subtle in its ambitions. Once executed, it targets:

  • CI/CD tokens — GitHub PATs, GITHUB_TOKEN, GitLab CI tokens, Jenkins credentials
  • Cloud provider credentials — AWS, GCP, and Azure metadata endpoints, Kubernetes service account tokens, Vault secrets
  • Container registry credentials — Docker config, deploy keys
  • .env files — the single richest target in most PHP applications
  • SSH keys — private keys from ~/.ssh/
  • Browser data — saved passwords, cookies, session tokens
  • Password manager vaults — locally cached credential stores
  • VPN configurations — connection profiles and stored credentials

All exfiltrated data was sent to a typosquatted domain designed to blend in with legitimate Laravel infrastructure. The payload was cross-platform, targeting Linux, macOS, and Windows hosts equally.

Why Composer Was Particularly Vulnerable

The PHP ecosystem has long lagged behind npm and PyPI in supply chain security tooling. While npm has npm audit, lockfile integrity checks, and provenance attestations, and PyPI now supports Trusted Publishing via OIDC, Composer’s security model still relies heavily on trust.

Several factors made this attack effective:

  • No tag signing enforcement. Composer does not verify GPG signatures on git tags. If a tag exists and points at a commit, Composer trusts it.
  • GitHub’s fork-tag reference model. GitHub allows tags in a repository to reference commits from any fork of that repository. This is a legitimate feature for collaboration, but it creates a trust boundary violation when combined with package managers that resolve dependencies via git tags.
  • Autoload as an execution vector. Composer’s autoload.files directive runs specified files on every request without any explicit require statement. This is convenient for helper functions but devastating when weaponised.
  • Lockfile discipline is inconsistent. Many PHP teams commit composer.lock for applications but not for libraries. Even those who commit lockfiles often run composer update in CI without verifying the lockfile hash against a known-good state.

Immediate Response: What Your Team Must Do Now

If your organisation uses any Laravel-Lang packages, here is your checklist:

1. Check Exposure

Search your composer.json and composer.lock files across all projects for references to laravel-lang/lang, laravel-lang/http-statuses, laravel-lang/attributes, or laravel-lang/actions. If present, determine whether any composer update or composer install ran on or after 22 May 2026 22:32 UTC.

2. Rotate Everything

If exposure is confirmed, treat every secret accessible to that environment as compromised. This includes CI provider tokens, cloud credentials, database connection strings, API keys in .env, SSH keys, and deploy keys. Rotate them all. No exceptions.

3. Audit Git Tags

Compare the commit hashes your lockfile references against known-good hashes from before the attack window. The Laravel-Lang maintainers have published verified hashes for legitimate releases.

4. Pin and Lock

Ensure every project commits composer.lock and that CI pipelines use composer install (which respects the lockfile) rather than composer update (which resolves fresh). This single practice would have prevented the attack for any team with a pre-attack lockfile.

Structural Defences: Beyond the Immediate Fix

Reacting to this specific attack is necessary but insufficient. The underlying vulnerability — unsigned tags, implicit trust in package registries, and permissive autoload execution — will be exploited again. Here is how to build structural resilience:

Network Egress Controls

Your CI/CD runners and production servers should not be able to make arbitrary outbound HTTP requests. Restrict egress to known-good destinations. If the credential stealer cannot phone home, exfiltration fails regardless of whether the payload executes.

Composer Audit in Your Pipeline

Run composer audit in every CI build. It checks installed packages against the PHP Security Advisories Database. While it would not have caught this specific zero-day, it raises the baseline and catches known vulnerabilities before they ship.

Lockfile Hash Verification

Generate and store a hash of your composer.lock file. Before any deployment, verify the hash matches. If someone has tampered with the lockfile — or if composer update ran unexpectedly — the hash mismatch halts the pipeline.

Dependency Review Automation

Tools like Socket, Snyk, and Dependabot now support Composer. Configure them to flag new dependencies, version changes, and — critically — changes to autoload directives. A new file appearing in autoload.files should trigger a human review.

Minimal CI Credentials

Follow the principle of least privilege for CI/CD tokens. A pipeline that only needs to push a Docker image should not have access to your cloud provider’s root credentials. Scope tokens tightly, use short-lived credentials where possible, and rotate regularly.

The Broader Pattern: Package Managers as Critical Infrastructure

This attack sits within a clear escalation pattern. In 2025, we saw npm typosquatting at scale. In early 2026, GitHub Actions were weaponised in the TanStack attack. Now Composer’s git tag model has been exploited. PyPI, RubyGems, and Cargo are not immune — they simply have not been hit with this specific technique yet.

Package managers were designed for convenience in an era of implicit trust. That era is over. The industry needs to move towards provenance attestations, signed releases, and reproducible builds as baseline expectations, not optional extras.

Oracle’s announcement this month that they are moving to monthly security patch updates starting 28 May 2026 — explicitly citing AI-accelerated vulnerability discovery — reinforces the same message. The attack surface is expanding faster than quarterly patch cycles can address. Monthly is better. Continuous is best.

What This Means for Your Team

If you are running PHP in production — and Laravel remains the most popular PHP framework by a considerable margin — this attack should trigger a concrete review of your supply chain security posture. Not a theoretical exercise, but a hands-on audit: do you commit lockfiles? Do you restrict CI egress? Do you scope CI tokens to minimum privileges? Do you have dependency review automation in place?

At REPTILEHAUS, we help development teams build and harden their CI/CD pipelines, implement supply chain security controls, and respond to incidents like this one. If your team needs help auditing your Composer dependency chain or tightening your deployment pipeline, get in touch.

The fifteen-minute window that compromised 700 package versions is a stark reminder: in software supply chain security, the cost of prevention is always lower than the cost of response.

📷 Photo by Markus Spiske on Unsplash