Fake Laravel Packages on Packagist Are Installing Backdoors. Here Is How to Check.
Three malicious Packagist packages disguised as Laravel utilities deploy a cross-platform RAT that gives attackers full shell access, reads your .env, and exfiltrates credentials. Here is what happened, how to check if you are affected, and what to do.
On March 4, 2026, security researchers flagged three malicious packages on Packagist — PHP's primary package repository — that were disguised as Laravel utilities. The packages install a cross-platform remote access trojan (RAT) that works on Windows, macOS, and Linux, giving attackers full shell access to any server running the compromised application.
This is not a theoretical vulnerability. Any Laravel application that installed these packages is running a persistent backdoor with access to your .env file, database credentials, API keys, and every file on the server.
The malicious packages
| Package | Downloads | Contains malware directly? |
|---|---|---|
nhattuanbl/lara-helper |
37 | Yes |
nhattuanbl/simple-queue |
29 | Yes |
nhattuanbl/lara-swagger |
49 | No — but requires lara-helper as a dependency |
The attacker also published three clean packages (nhattuanbl/lara-media, nhattuanbl/snooze, nhattuanbl/syslog) to build credibility on Packagist before publishing the malicious ones. This is a common supply chain attack pattern: establish trust first, then weaponise.
How the attack works
Both lara-helper and simple-queue contain a file named src/helper.php that uses heavy obfuscation:
- Control flow obfuscation — scrambled execution paths that make static analysis difficult
- Encoded strings — domain names, command names, and file paths are encoded rather than stored as plaintext
- Randomised identifiers — variable and function names are random strings to evade pattern matching
When your Laravel application boots or autoloads the package's classes, helper.php executes automatically. It:
- Profiles your system — collects hostname, OS, PHP version, and installed packages
- Reads your environment — extracts the full contents of
.envincluding database credentials, API keys, andAPP_KEY - Opens a reverse shell — connects to the attacker's command-and-control (C2) server
- Persists — retries the C2 connection every 15 seconds in a loop, so even if the server is temporarily down, the RAT will reconnect when it comes back
Because the RAT runs in the same PHP process as your Laravel application, it has identical filesystem permissions and access to every environment variable. There is no privilege boundary between the RAT and your application code.
The C2 server is down — am I safe?
No. The RAT is configured to retry indefinitely. If the attacker brings the C2 server back online, or if the domain is re-registered, every compromised application will reconnect automatically. A non-responsive C2 server means the attacker is not currently issuing commands, not that the backdoor is gone.
How to check if you are affected
Step 1: Search your dependencies
# Check installed packages
composer show | grep nhattuanbl
# Search composer.lock directly
grep -r "nhattuanbl" composer.lock
If either command returns results, your application is compromised.
Step 2: Search your vendor directory
# Look for the malicious helper file
find vendor -name "helper.php" -path "*/nhattuanbl/*"
Step 3: Check composer.json history
Even if the packages have been removed, check your git history to see if they were ever installed:
git log -p --all -S "nhattuanbl" -- composer.json composer.lock
Remediation steps
If you find any of these packages in your project, treat it as a full compromise:
1. Remove the packages immediately
composer remove nhattuanbl/lara-helper nhattuanbl/simple-queue nhattuanbl/lara-swagger
2. Rotate every secret
Every credential in your .env file must be considered compromised:
- APP_KEY — run
php artisan key:generateand redeploy - Database passwords — change in your database server, then update
.env - API keys — regenerate keys for every third-party service (Stripe, AWS, SendGrid, etc.)
- Mail credentials — reset SMTP passwords
- OAuth secrets — regenerate client secrets for any OAuth integrations
3. Audit for lateral movement
# Check for recently modified files outside vendor/
find . -newer composer.lock -not -path "./vendor/*" -not -path "./.git/*" -name "*.php" -type f
# Check for unauthorized cron jobs
crontab -l
# Review recent database activity
php artisan tinker --execute="DB::table('users')->where('created_at', '>', now()->subDays(7))->get(['id','email','created_at'])"
4. Check outbound network connections
# Look for suspicious outbound connections from the PHP process
ss -tp | grep php
netstat -an | grep ESTABLISHED | grep php
5. Consider re-provisioning
If you confirm the RAT was active while the C2 server was responsive, the safest approach is to re-provision your server from a clean state rather than trying to clean a compromised system.
Why this keeps happening
This attack exploits the same trust model that makes Composer convenient: you run composer require and trust that the package does what it says. Packagist does not perform security review on uploaded packages. Anyone can publish anything.
This is not unique to PHP. The npm ecosystem sees hundreds of malicious packages per month. PyPI has the same problem. The OWASP Top 10 2025 elevated Software Supply Chain Failures to position #3, reflecting how systemic this risk has become.
How to reduce your supply chain risk
- Audit new dependencies before installing — check the author's profile, download count, and repository activity
- Run
composer auditin CI — catches known CVEs in your dependency tree - Pin exact versions — use exact version constraints in
composer.jsonrather than^ranges for critical packages - Review autoloaded files — check what a package registers in its
composer.jsonautoload section before installing - Monitor your application externally — supply chain attacks change what your application does in production, and external monitoring catches behavioral changes that code review misses
- Use
composer.lock— always commit your lock file and runcomposer install(notupdate) in production
The bigger picture
Low download counts (37, 29, 49) might make this seem like a small incident. But consider:
- Each download potentially represents a production application
- The attacker built credibility with clean packages first, showing sophistication
- The RAT persists indefinitely and will reconnect if the C2 comes back
- The packages had legitimate-sounding names that a developer might install without suspicion
Supply chain attacks do not need to be widespread to be devastating. A single compromised dependency in a single application is enough to exfiltrate every secret in your environment.
Frequently Asked Questions
Which Laravel packages on Packagist are malicious?
The malicious packages are nhattuanbl/lara-helper (37 downloads), nhattuanbl/simple-queue (29 downloads), and nhattuanbl/lara-swagger (49 downloads). The lara-swagger package does not contain malicious code directly, but lists lara-helper as a dependency, causing the RAT to install automatically. The same author published three clean packages (lara-media, snooze, syslog) to build credibility.
How do I check if my Laravel project installed a malicious package?
Run composer show | grep nhattuanbl in your project directory. If any results appear, your application is compromised. Also check your composer.lock file for any of the three package names. Even if the C2 server is currently non-responsive, the RAT retries the connection every 15 seconds, so it will activate if the server comes back online.
What does the Laravel Packagist RAT do?
The RAT gives the attacker full remote shell access to your server. It runs in the same process as your Laravel application with the same filesystem permissions, meaning it can read your .env file, database credentials, API keys, and any file accessible to the web server. It also profiles your system and sends host information to the command-and-control server.
What should I do if I installed one of the malicious Laravel packages?
Assume full compromise. Remove the packages immediately with composer remove. Rotate every secret in your .env file: database passwords, API keys, APP_KEY, mail credentials, and any third-party service tokens. Audit outbound network traffic for connections to the C2 server. Check for any unauthorized changes to your codebase or database. Consider re-provisioning the server from a clean state.
Related Articles
Laravel Debug Mode in Production: Why It's Dangerous and How to Fix It
Debug mode in production exposes stack traces, database credentials, environment variables, and internal paths. Learn exactly what it reveals, how attackers use it, and how to make sure it never reaches production.
SecurityOWASP Top 10 for Laravel: A Practical Guide
A hands-on mapping of every OWASP Top 10 (2021) category to specific Laravel vulnerabilities, with code examples of what goes wrong and how to fix it.
SecurityIs Your Laravel .env File Exposed? How to Check and Fix It
Your .env file contains database credentials, API keys, and encryption secrets. If it's accessible from the web, attackers already have everything they need. Here's how to check and fix it.