CVE-2026-54182 Overview
CVE-2026-54182 is a command injection vulnerability in backpack/crud, a Laravel package providing Create, Read, Update, and Delete (CRUD) functionality for Backpack administration panels. The flaw resides in Backpack\CRUD\Stats::makeCurlRequest inside src/Stats.php, which is invoked from BackpackServiceProvider::boot(). The function builds a shell command containing a URL derived from the HTTP Host header and passes it to PHP's exec() without adequate shell neutralization. An unauthenticated attacker who supplies a malformed Host value can inject operating-system commands. The weakness is classified as [CWE-20] Improper Input Validation.
Critical Impact
Successful exploitation executes arbitrary OS commands as the web-server user, exposing environment secrets, files, and reachable internal services, and enabling data modification or service disruption.
Affected Products
- backpack/crud versions prior to 4.1.70
- backpack/crud 5.x versions prior to 5.6.2
- backpack/crud 6.x versions prior to 6.8.13 and 7.x prior to 7.0.36
Discovery Timeline
- 2026-09-14 - CVE-2026-54182 published to the National Vulnerability Database (NVD)
- 2026-09-14 - Last updated in NVD database
Technical Details for CVE-2026-54182
Vulnerability Analysis
The vulnerable code path is reached during framework bootstrap through BackpackServiceProvider::boot(), which calls the stats reporter. Inside Stats.php, the reporter constructs a shell command by concatenating a URL string into a curl invocation. The URL is influenced by the HTTP Host header of the incoming request, and the concatenated command is then executed via PHP's exec().
Because the Host value is embedded into the command line without shell metacharacter neutralization, a crafted Host header can break out of the intended argument and append arbitrary shell commands. The reporter is gated by a rand(1, 100) != 1 sampling check, but repeated requests reach that gate probabilistically, making the condition trivially satisfiable at scale.
Root Cause
The root cause is the unsafe construction of a shell command string using attacker-controlled input, combined with invocation of exec() instead of a safe HTTP client. The code assumed the Host header was trustworthy and did not escape shell metacharacters or use argument-array execution.
Attack Vector
An unauthenticated remote attacker sends HTTP requests with a malicious Host header to any endpoint served by an application that boots the Backpack service provider. The attack requires that exec() is enabled and the curl binary is available on the host. Reverse-proxy Host header validation and PHP configurations that disable exec() reduce reachability but do not remediate the vulnerable code.
// Vulnerable construction removed by the patch (src/Stats.php)
// Source: https://github.com/Laravel-Backpack/CRUD/commit/0f2faafc22a15d77c14370f163d8f739f933c28c
if (function_exists('exec') && extension_loaded('curl')) {
$this->makeCurlRequest($method, $url, $stats);
} else {
$this->makeGuzzleRequest($method, $url, $stats);
}
private function makeCurlRequest($method, $url, $payload)
{
$cmd = 'curl -X '.$method." -H 'Content-Type: application/json'";
$cmd .= " -d '".json_encode($payload)."' "."'".$url."'";
$cmd .= ' > /dev/null 2>&1 &';
exec($cmd, $output, $exit);
return $exit == 0;
}
The fix refactors the stats module to use Guzzle exclusively and removes the exec() code path entirely. See the Laravel Backpack Security Advisory GHSA-mrc5-3mm3-45c5.
Stop Remote Code Execution Before It Runs
Singularity™ Endpoint detects and blocks exploit attempts at machine speed, including zero-days and novel attack techniques.
Stop Exploit AttemptsDetection Methods for CVE-2026-54182
Indicators of Compromise
- HTTP requests containing shell metacharacters (`, $(, ;, |, &) inside the Host header.
- Web server processes (php-fpm, apache, nginx worker) spawning curl, sh, bash, or /bin/sh -c child processes.
- Outbound network connections initiated by the PHP or web-server user to attacker-controlled hosts shortly after inbound HTTP traffic.
Detection Strategies
- Inspect application and reverse-proxy access logs for anomalous Host header values that deviate from the configured server names.
- Alert on process-lineage patterns where a PHP interpreter spawns curl followed by additional shell commands.
- Correlate high-volume request bursts to the same URI paths, which may indicate an attacker attempting to hit the 1-in-100 sampling gate.
Monitoring Recommendations
- Enable and forward PHP error_log and web-server access logs to a centralized analytics platform for retrospective hunting.
- Monitor egress traffic from application servers for connections to previously unseen external destinations.
- Track the installed backpack/crud version across your fleet via Composer lockfile inventory to identify unpatched hosts.
How to Mitigate CVE-2026-54182
Immediate Actions Required
- Upgrade backpack/crud to 4.1.70, 5.6.2, 6.8.13, or 7.0.36 (or later) as appropriate for your major version.
- Enforce strict Host header allowlisting at the reverse proxy or load balancer to reject malformed values before they reach PHP.
- Disable exec() in php.ini via the disable_functions directive on servers that do not require it.
Patch Information
The issue is fixed in backpack/crud versions 4.1.70, 5.6.2, 6.8.13, and 7.0.36. The patches refactor src/Stats.php to use Guzzle exclusively, remove the makeCurlRequest function that invoked exec(), and restrict stats reporting to admin-panel routes only. See Laravel Backpack Pull Request #6012 and the Laravel Backpack Release 7.0.36 notes for details.
Workarounds
- Configure the web server or reverse proxy to validate the Host header against an allowlist and reject non-conforming values with HTTP 400.
- Add exec to the disable_functions list in php.ini to prevent the vulnerable code path from executing shell commands.
- Ensure the curl binary is not available in the PHP execution PATH on hosts where it is not required.
# php.ini hardening: disable exec() to block the vulnerable code path
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
# nginx: restrict Host header to expected values
server {
listen 80 default_server;
server_name _;
return 444;
}
server {
listen 80;
server_name admin.example.com;
# ... normal application config
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

