When Git Tags Become Weapons: The Attack That Shocked the Laravel Community

Overview of the campaign
On the evening of May 22, 2026, the GitHub Laravel-Lang organization (a popular community translation project in the PHP/Laravel ecosystem) experienced an infrastructure breach, leading to a widespread supply chain poisoning campaign. The attacker performed a force-push, overwriting more than 700 historical Git tags belonging to four popular Composer packages: laravel-lang/lang, laravel-lang/http-statuses, laravel-lang/attributes, and laravel-lang/actions.
Instead of releasing a new version, the attacker redirected all the old version tags to malicious commits in a separate forked repository. When developers or CI/CD systems ran the library update command, the Composer package manager automatically pulled in the source code containing the PHP InfoStealer malware. This malware could siphon off all sensitive configurations, including cloud account keys (AWS, Azure, GCP), K8s tokens, HashiCorp Vault secrets, and CI/CD secrets, then exfiltrate them to a C2 server.
Due to the extremely high popularity of Laravel in Vietnam, both in software outsourcing and independent products, companies using PHP need to immediately check the composer.lock file, remove the compromised versions, and rotate all secret keys in both development and production environments.
Event Timeline
| Time (UTC) | Event | Technical details |
|---|---|---|
| 22/05/2026 22:32 | Start of the poisoning campaign | The attacker gained push access to the Laravel-Lang organization and began force-pushing the first malicious tag targeting the laravel-lang/lang package. |
| 22/05/2026 23:24 | Complete flagship package | All 502 historical tags of the core translation package laravel-lang/lang were completely redirected to malicious commits. |
| 22/05/2026 23:25 - 00:00 | Expand the scale of the attack | Continue overwriting tags in bulk on three additional library packages: http-statuses, attributes, and actions. |
| 23/05/2026 00:00 | End of the poisoning process | Completed the force-push tag of the laravel-lang/actions package. All four repositories redirected old tags to the malicious fork. |
| 23/05/2026 00:17 | Detonation & Independent Analysis | StepSecurity successfully activated the malware test on independent Actions runners, recording the entire network flow and temporary system files. |
| 23/05/2026 08:00 | Community Alert | Socket and Aikido Security simultaneously released analysis reports, officially warning the global Laravel development community. |
Affected versions
| Package Name | Scope of Impact (Total Tags) | Poisoned Version / Example |
|---|---|---|
laravel-lang/lang |
All 502 tags | 15.29.5, 15.29.1, 2.0.4, 1.0.2,... (including all 12.x, 13.x, 14.x, 15.x series) |
laravel-lang/http-statuses |
All versions from v1.0.0 to v3.4.5 | v3.4.5, v3.4.0, v3.0.0, v2.0.0, v1.0.0,... |
laravel-lang/actions |
All 46 tags | 1.12.2, 1.10.0, 1.0.0,... (from 1.0.0 to 1.12.2) |
laravel-lang/attributes |
All 86 tags | v2.4.1, 2.6.0, 2.5.0,... |
Detailed Technical Analysis
Git Tag Poisoning Technique
Typically, developers trust that older, stable released versions will never have their source code changed. However, Git allows force-pushing to update tags to point to a new commit.
In this campaign, the attacker cleverly exploited a specific GitHub mechanism: allowing a Git tag from the main repository to point directly to a commit in a third-party fork repository. By redirecting version tags (e.g., v3.4.5, v1.0.2, etc.) to a malicious commit in a fork controlled by the attacker, they avoided making any pull requests or direct modifications to the main branches (main/developer) of Laravel-Lang.
For PHP's Composer package manager, when a developer requests a specific tag, Composer downloads the zip package corresponding to the commit that tag points to. As a result, the victim's application downloads malicious source code without any alerts from the usual Git checks on the main branch.
Autoload Trigger Mechanism
The attacker inserted a malicious file at the path src/helpers.php and registered it in the composer.json file under the autoload.files key.
Composer supports three autoload mechanisms. The two class-loading mechanisms (psr-4 and classmap) operate on a lazy loading principle—loading files only when the class is instantiated in the code. In contrast, the file-loading mechanism (files) operates on an eager loading principle—all files listed are loaded via the require command as soon as the vendor/autoload.php file is called.
Since every Laravel or Symfony project starts by importing vendor/autoload.php right at the entry point (public/index.php file or CLI startup script), the malicious code inserted in helpers.php will automatically execute immediately when the application boots, without requiring any interaction from the developer.
Analysis of Payload Stage-1 (Dropper)
The malicious code in src/helpers.php operates very subtly with sequential execution steps to evade the control system:
Dynamic C2 Decoding: The command and control server domain flipboxstudio[.]info is dynamically constructed in memory using an array of ASCII codes through the function array_map('chr', [...]). This technique helps bypass static keyword-based scanners (YARA or static regex).
Bypass TLS and Load Stage-2: The script calls cURL to download the payload from the address https://flipboxstudio\[.\]info/payload. To ensure the payload downloads successfully in any environment (including internal networks under surveillance or SSL/TLS decryption), the attacker configures cURL to bypass TLS certificate verification (CURLOPT_SSL_VERIFYPEER = 0 and CURLOPT_SSL_VERIFYHOST = 0).
Background Detachment: The downloaded payload is saved in the system's temporary directory as a hidden file (e.g., /tmp/.laravel_locale/<12_hex_chars>.php). The dropper activates this file by running a background system command (php /tmp/.laravel_locale/xxx.php > /dev/null 2>&1 & on Linux, or using the WScript.Shell object on Windows). This technique ensures the malicious process remains independent even after the main PHP web processing thread ends.
Self-Erasing Traces (Anti-Forensics): Within just 3 seconds of execution, the malware issues a command to delete the newly created loader file and the associated ELF executable file, leaving no physical trace on the hard drive, which significantly complicates post-incident analysis.
Analysis of Payload Stage-2 (Stealer Framework "DebugElevator")
When loaded into memory as an independent process reparented to init (ppid=1), the second payload initializes the Stealer class, featuring an extensive structure with 17 data collection modules ("Collectors"). The collected data is XOR encrypted with the hardcoded key k9X2mP7vL4nQ8wR1 before being sent to https://flipboxstudio\[.\]info/exfil.
Detailed behavior of the standout Collectors includes:
Cloud & AWS Collector: Directly queries the Cloud Metadata Service address (EC2 IMDS at 169.254.169.254) to steal IAM roles and instance identity. It also scans local configuration files of Azure, Google Cloud (gcloud), DigitalOcean, Heroku, Netlify, and Vercel.
Kubernetes Collector: Searches for and steals Kubernetes Service Account tokens at /var/run/secrets/kubernetes.io/serviceaccount/token and local kubeconfig files.
HashiCorp Vault Collector: Searches for Vault tokens in the system environment, automatically performing recursive queries to the Vault API to extract the entire Key-Value store.
CI/CD Collector: Reads the entire configuration file of the Jenkins build server (including the master.key encryption key and credentials.xml), GitLab Runners, GitHub Actions, CircleCI, and TravisCI.
Browser Collector & Windows Decryptor: Steals cookies, history, and login information from Chrome, Edge, Firefox, Brave, and Opera. To counter the new App-Bound Encryption protection mechanism introduced by Google from Chrome v127+, the malware releases an embedded Windows PE file named DebugChromium.exe. This file runs under user privileges to interact with the Windows system service, extracting the Master Key decryption key and decrypting all passwords. Firefox is decrypted directly through the NSS library.
VPN & Credentials Collector: Collects VPN configuration files (.ovpn, .conf) from OpenVPN, WireGuard, and commercial services like NordVPN and ExpressVPN. Scans the entire machine for .env files, SSH private keys, and Git configuration files to obtain GitHub/GitLab credentials.
Summary of impact
For programmers
Programmers' computers are a top priority target as they often contain a lot of important credentials. The malware can search for and steal:
SSH Private Keys
GitHub Personal Access Tokens
GitLab Access Tokens
Docker Credentials
AWS CLI Credentials
Azure Credentials
Google Cloud Credentials
The .env file contains the project's secrets.
For CI/CD systems
CI/CD servers often contain secrets with higher privileges than programmer accounts. The detected payload can collect:
GitHub Actions Secrets
GitLab CI/CD Variables
Jenkins Credentials
Container Registry Credentials
Deployment Tokens
This allows attackers to expand their reach from an infected package to the entire software development process of the enterprise.
For Cloud and Kubernetes environments
One of the most notable behaviors is the malware's attempt to access the metadata service address: 169.254.169.254. This address is used by AWS, Azure, and many other cloud platforms to provide temporary credentials to servers.
Additionally, the malware also searches for:
Kubernetes Service Account Tokens
kubeconfig files
Kubernetes Secrets
Cluster Credentials
If this information is stolen, attackers can take control of the entire Kubernetes cluster or related cloud resources.
For end users
In cases where the malware is executed on a workstation or desktop environment, the payload can access:
Browser Cookies
Session Tokens
Saved Passwords
Cryptocurrency Wallets
Application Authentication Tokens
This can lead to account takeover or theft of personal data.
IOCs
Network Indicators
Host-based Indicators
/tmp/.laravel_locale/
/tmp/.laravel_locale/[12_hex_characters].php
/tmp/.[8_hex_characters]
DebugChromium.exe
MITRE ATT&CK (MITRE ATT&CK Mapping)
| Tactic | Technique ID | Technique Name | Description in the Campaign |
|---|---|---|---|
| Initial Access | T1195.002 | Supply Chain Compromise: Compromise Software Dependencies | Poisoning Git tags to point to a forked commit of four Laravel-Lang packages on Packagist. |
| Execution | T1059.008 | Command and Scripting Interpreter: Network Shell / Scripting | Automatic execution of malicious code through Composer Eager Autoloader (autoload.files). |
| Defense Evasion | T1027 | Obfuscated Files or Information | Rebuild the C2 domain name in memory using an ASCII array to avoid static scanning signatures. |
| T1070.004 | Indicator Removal: File Deletion | Automatically delete php loader file and ELF binary in /tmp after 3 seconds. | |
| Credential Access | T1555 | Credentials from Password Stores | Collect passwords from Chromium and Firefox browsers. |
| T1552.001 | Unsecured Credentials: Credentials In Files | Scan the drive to search for SSH private keys, .env files, and Kubernetes configuration files. | |
| Command & Control | T1071.001 | Application Layer Protocol: Web Protocols | Use cURL to send HTTP/HTTPS requests across firewalls to download payload and push data. |
| Exfiltration | T1048.003 | Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted/Encrypted Non-Attribution Channel | Encrypt XOR the collected sensitive data and push it to the /exfil address of C2. |
Expert Analysis
From the perspective of operating a Security Operations Center (SOC), we assess this campaign as having a very high level of technical sophistication. The attacker did not choose the traditional method of directly inserting code into the main branch (which is easily detected by source control mechanisms and the project's automated testing). The use of Git Tag Poisoning to cross-reference commits to a forked repository shows that the attacker has a deep understanding of how GitHub and Composer Packagist infrastructures work.
In the Vietnamese market, PHP in general and Laravel in particular dominate the web application development sector, especially for outsourced projects targeting Japan, Korea, and Europe. The use of native language packages like laravel-lang is mandatory for most systems.
The habit of directly storing cloud API keys (AWS, GCP) and database passwords with root/admin privileges inside the .env file on a developer's personal computer is extremely common. Therefore, if the development machine or staging server runs the composer update command and hits a poisoned tag between the night of 05/22 and 05/23/2026, the company's entire digital resources are essentially exposed to the attacker.
Recommendation
Urgent (Objective 0 - 24 hours)
Check version locks: Immediately review the composer.lock file. If this file was updated or recreated from 22:32 UTC on 05/22/2026 onwards, compare the commit hashes of the laravel-lang packages with the list of malicious commits outlined in the IOC section.
Secure commit fix: If using a translation package is necessary, configure composer.json to point to a specific commit hash from before 05/22/2026 (e.g., use a Git commit SHA instead of a dynamic version tag).
Rotate credentials: If a system is found to have installed a malicious version, immediately assume the environment is fully compromised. Proceed with rotating (revoke and regenerate):
Cloud access keys (AWS Access Key ID/Secret, Azure Service Principal, GCP Service Account).
Database passwords configured in .env.
GitHub/GitLab tokens used in CI/CD.
SSH keys used to access servers.
Short term (Objective 1 - 7 days)
Scan for process traces: Activate process monitoring scripts on production and development servers. Look for PHP processes or unnamed processes with a parent ID of 1 (ppid=1).
Network blocking configuration: Create blocking rules on the firewall or system-wide DNS sinkhole for the domain flipboxstudio[.]info.
Review CI/CD logs: Check the execution logs of the build servers (GitHub Actions runner, GitLab runner) to search for unusual DNS requests going out to the internet.
Long term
Apply Egress Filtering for Runner: Use outbound traffic control solutions for CI/CD runners (e.g., StepSecurity Harden-Runner in Block mode). Allow runners to connect only to predefined trusted addresses (such as github.com, packagist.org).
Lockfile Enforcement: Direct execution of the composer update command is strictly prohibited in the production environment. The production environment is only allowed to run composer install based on the composer.lock file that has been reviewed and approved in the staging environment.
Source code repository protection configuration: For open library administrators, it is mandatory to enable two-factor authentication (2FA) and configure tag protection rules on GitHub to prevent force-push actions that overwrite historical tags.
Refer
Malware Found in Laravel-Lang Composer Packages After Git Tag Poisoning Attack
Laravel Lang Compromised with RCE Backdoor Across 700+ Versi...





