Table of contents

Laravel-Lang Composer tag-rewrite Supply Chain Attack

Laravel-Lang Composer tag-rewrite Supply Chain Attack - Blog Cover Threat news

On 2026-05-22, an attacker rewrote every repository tag across four Composer packages in the Laravel-Lang ecosystem to point at malicious commits. The affected packages are laravel-lang/lang, laravel-lang/attributes, laravel-lang/http-statuses, and laravel-lang/actions. The rewrite took place on 2026-05-22 into the early hours of 2026-05-23. Every malicious commit makes the same two-file change: one entry added to composer.json, and one new file at src/helpers[.]php. This article walks through both files as they actually exist in a poisoned tree.

The compromise

The malicious commits in all four repositories share the same git author identity, Your Name <you@example.com>. The commits are not reachable from any branch in the upstream repositories; only the rewritten tags point to them. The combination of the shared author identity, the orphan-commit topology, and the compressed rewrite window across four repositories is consistent with one operator running through the four targets in sequence.

The composer.json change

The poisoned manifest’s autoload block contains two entries:

"autoload": {
   "psr-4": {
       "LaravelLang\\Lang\\": "src/"
   },
   "files": [
       "src/helpers.php"
   ]
}

The PSR-4 entry maps the package’s LaravelLang\Lang\ namespace to src/. The "files" entry is the attack vector.

Composer’s autoload.files directive is documented to load every listed file immediately when an application requires vendor/autoload.php. Unlike PSR-4 entries, which are lazy and only load classes on first reference, autoload.files entries are eager: they execute the moment the autoloader is bootstrapped. In a Laravel application this happens on every HTTP request boot. In a Composer-using CLI tool it happens on every command invocation. In a CI workflow it happens the first time any step touches the project’s autoload.

Inside helpers.php

The dropper opens with two decoy functions, laravel_lang_locale() and laravel_lang_fallback(), that wrap Laravel’s config() and return the application locale. The malicious behavior lives in an anonymous closure guarded by a LARAVEL_LANG_HELPERS define-check. The closure runs once per host, and the once-enforcement is a marker file:

Laravel-Lang Composer tag-rewrite Supply Chain Attack - image

The marker filename is an MD5 over three values: the install directory, the host’s network name returned by php_una‌me('n'), and the inode of helpers.php itself. The closure returns early on a second invocation, so the dropper fires exactly once per vendor/ tree per host.

The C2 host is kept out of plain-text scans by reconstructing it from a byte array:

Laravel-Lang Composer tag-rewrite Supply Chain Attack - image 1

The byte array spells flipboxstudio[.]info.

The fetcher tries file_get_‌contents first with a custom stream context, then falls back to libcurl if the first returns less than 50 bytes. Both transports set verify_peer => false, CURLOPT_SSL_VERIFYPEER => false, and a spoofed Mozilla/5.0 User-Agent. The 50-byte minimum is the dropper’s signal-quality check: it tolerates a transport failure but rejects an empty or near-empty response.

If the fetch returns content, the dropper writes the response to a random filename under sys_get_temp‌_dir()/.laravel_locale/ (bin2hex(random_bytes(6)) produces a 12-hex-character name) and branches on OS for launch. On Linux and macOS the launch is ex‌ec("php \"$f\" > /dev/null 2>&1 &"). On Windows the dropper writes a 4-byte-randomized .vbs shim that calls WScript.‌Shell.Run with a non-blocking flag, invoked from cscript //nologo //b. Every filesystem and network call in the closure uses PHP’s @ error-suppression operator, so no warning or stack trace reaches PHP-FPM, the web server, or error_log.

The full closure is roughly fifty lines of PHP. By the time control returns from vendor/autoload.php, the stage-two PHP is already running detached in the background.

What runs next

Analysis of the stage-two payload served from hxxps://flipboxstudio[.]info/payload shows a PHP credential stealer targeting cloud, container, and developer-machine credentials: EC2 instance metadata at 169.254.169.254, Kubernetes service-account tokens at /var/run/secrets/, HashiCorp Vault, Jenkins master.key and credentials.xml, Linux /proc/<pid>/environ and /cmdline, and Chrome v127+ App-Bound Encryption via a dropped DebugChromium.exe. The harvested data is XOR-encrypted with the key k9X2mP7vL4nQ8wR1 and POSTed to hxxps://flipboxstudio[.]info/exfil.

Indicators of compromise

CategoryIndicator
C2 domainflipboxstudio[.]info
Stage-one URLhxxps://flipboxstudio[.]info/payload
Stage-two exfil URLhxxps://flipboxstudio[.]info/exfil
Drop directory<sys_get_temp‌_dir>/.laravel_locale/
Stage-two PHP filename^[0-9a-f]{12}\.php$
Windows launcher filename^[0-9a-f]{8}\.vbs$
Windows stage-three binaryDebugChromium.exe
Cloud-metadata egressOutbound to 169.254.169.254 from a PHP process
In-process constantLARAVEL_LANG_HELPERS
composer.json indicator"files": ["src/helpers.php"] entry under autoload
Affected packageslaravel-lang/lang, laravel-lang/attributes, laravel-lang/http-statuses, laravel-lang/actions
Rewrite window2026-05-22 into 2026-05-23
Malicious commit authorYour Name <you@example.com>

Remediation

  1. Block flipboxstudio[.]info at DNS and HTTPS proxy layers, then investigate.
  2. Audit composer.lock against upstream history. For each source.reference SHA recorded under laravel-lang/lang, laravel-lang/attributes, laravel-lang/http-statuses, or laravel-lang/actions, look the SHA up in the upstream repository and check the commit author. Any commit authored by Your Name <you@example.com> is a poisoned install. Lockfiles whose pinned SHAs pre-date 2026-05-22 and are reachable from upstream branch history are safe, provided no composer update has run since.
  3. Reinstall against a known-good commit. Tag-based version constraints in composer.json resolve to whatever the rewritten tag now points at, so re-running composer install against a tag constraint is not sufficient. Pin each affected laravel-lang/* dependency to a commit SHA that pre-dates 2026-05-22 and is reachable from upstream branch history, then run composer update <package> to refetch. Confirm afterwards that vendor/laravel-lang/*/composer.json no longer contains the "files": ["src/helpers.php"] autoload entry and that src/helpers.php is no longer in the package tree.
  4. Remove working artifacts. Delete <sys_get_temp‌_dir>/.laravel_locale/ on every affected host.
  5. Rotate credentials. On CI runners that ran the install, rotate every cloud key, registry token, and deploy key the workflow had access to, and audit the job’s GitHub API activity. On developer machines, treat the host as fully compromised.
  6. Going forward, treat the lockfile’s pinned commit SHAs as the source of truth and verify each SHA is reachable from the upstream repository’s branch history before deploying. Tag-based resolution alone does not detect the kind of tag rewrite seen in this incident.

Mend.io coverage

Mend.io has issued an MSC covering all four affected Laravel-Lang Composer packages:

  • MSC-2026-5762

References

https://socket.dev/blog/laravel-lang-compromise

Aikido Security: https://www.aikido.dev/blog/supply-chain-attack-targets-laravel-lang-packages-with-credential-stealer

Laravel-Lang/attributes issue #1085: https://github.com/Laravel-Lang/attributes/issues/1085

StepSecurity: https://www.stepsecurity.io/blog/laravel-lang-supply-chain-attack

Manage open source risk

Recent resources

Laravel-Lang Composer tag-rewrite Supply Chain Attack - Mini Shai Hulud is Back 1

Mini Shai-Hulud Hits @antv: 323 npm Packages Compromised Through the atool Maintainer Account

Mini Shai-Hulud strikes again: 323 npm packages compromised via @antv's atool.

Read more
Laravel-Lang Composer tag-rewrite Supply Chain Attack - Mend securing RubyGems

Inside the RubyGems Supply Chain Attack: How Mend Defender Caught a Coordinated Flood Before It Spread

How Mend.io caught a coordinated RubyGems attack and what it teaches us.

Read more
Laravel-Lang Composer tag-rewrite Supply Chain Attack - Mini Shai Hulud is Back

Mini Shai-Hulud Is Back: 172 npm and PyPI Packages Compromised in Latest Wave

Shai-Hulud's largest wave: 172 npm and PyPI packages compromised in 48 hours.

Read more