Skip to main content

Command Palette

Search for a command to run...

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

Updated
12 min read
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:

  1. 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).

  2. 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).

  3. 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.

  4. 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)

  1. 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.

  2. 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).

  3. 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)

  1. 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).

  2. Network blocking configuration: Create blocking rules on the firewall or system-wide DNS sinkhole for the domain flipboxstudio[.]info.

  3. 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

  1. 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).

  2. 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.

  3. 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...

Laravel-Lang Supply Chain Attack: Every Tag Across Multiple Composer Packages Rewritten to Steal CI Secrets - StepSecurity

More from this blog

F

FPT IS Security

824 posts

Dedicated to providing insightful articles on cybersecurity threat intelligence, aimed at empowering individuals and organizations to navigate the digital landscape safely.