Sep 9, 2026·6 min read·5 visits
Unauthenticated remote command execution in Composer's Perforce VCS driver via malicious repository configurations or lock files.
A critical remote code execution vulnerability exists in the Composer PHP dependency manager due to improper neutralization of command parameters passed to the Perforce CLI client. Unauthenticated attackers can exploit this flaw via crafted package metadata in custom repositories or lock files, triggering arbitrary OS command execution when a user or automated CI/CD pipeline runs Composer commands.
Composer is the standard dependency manager for the PHP ecosystem, responsible for fetching, resolving, and installing package dependencies. To support diverse version control systems, Composer includes dedicated VCS drivers, including one for Perforce. This Perforce driver allows Composer to pull package sources directly from Perforce repositories.
The vulnerability, designated as CVE-2026-84361, is classified under CWE-78 (OS Command Injection). It arises because Composer's Perforce utility fails to sanitize or restrict the package-defined source URL before passing it to the local Perforce command-line client (p4). When a package configuration defines a Perforce source type, its URL is directly mapped to the P4PORT configuration parameter.
An attacker can abuse this behavior by crafting a repository configuration or a composer.lock file containing a malicious URL prefixed with rsh: or jsh:. If the system running Composer has the p4 CLI client installed, standard actions like composer install or composer update will automatically execute local shell commands embedded in the URL.
The root cause of CVE-2026-84361 lies in the underlying behavior of the Perforce CLI client (p4) in conjunction with Composer's unchecked parameter forwarding. To establish a connection with a Perforce server, the p4 client relies on the endpoint address specified via the P4PORT variable or the -p parameter. By default, this address represents a network location, such as a TCP or SSL socket.
However, Perforce natively supports alternative transport protocols for advanced scripting and tunneling configurations, specifically rsh: and jsh:. When the P4PORT parameter begins with these transport prefixes, the p4 executable does not connect over the network. Instead, it spawns the remainder of the parameter string as a local subprocess and pipes standard input/output through it to communicate.
In vulnerable versions of Composer, the Composer\\Util\\Perforce class processes package-defined URLs without validating their protocol scheme. When checking if a server exists or cloning a repository, Composer invokes p4 via a subprocess executor, passing the untrusted URL as the -p argument. Because this execution is a native feature of the p4 binary, traditional argument escaping or shell sanitization routines are ineffective. The command is not executed via a shell wrapper but is launched directly by the compiled p4 executable itself.
To understand the vulnerable path, we can examine how Composer handles Perforce URLs during repository verification. In vulnerable versions, the Perforce::checkServerExists() method executed a connection probe without verifying the format of the $url variable:
public static function checkServerExists(string $url, ProcessExecutor $processExecutor): bool
{
// Vulnerable: The $url parameter is passed directly to the p4 client via -p
return 0 === $processExecutor->execute(['p4', '-p', $url, 'info', '-s'], $ignoredOutput);
}The corresponding patch introduces a strict validation helper isValidPort() in src/Composer/Util/Perforce.php to filter out non-network endpoints before they reach the executable:
public static function isValidPort(string $url): bool
{
// Reject any transport keywords like rsh or jsh to prevent local subprocess execution
if (Preg::isMatch('{^\\s*+(?:rsh|jsh)\\s*+:}i', $url)) {
return false;
}
// Enforce strict whitelist of allowed tcp/ssl socket patterns
return Preg::isMatch('{^(?:(?:tcp|ssl)(?:4|6|46|64)?:)?(?:\\\\[[0-9a-f:.]++\\\\]|[a-z0-9._][a-z0-9._-]*+)(?::[a-z0-9._][a-z0-9._-]*+)?$}iD', $url);
}Additionally, this validation check is called during package loading inside ValidatingArrayLoader.php to catch unsafe URLs early and throw a SecurityException. The use of the /D modifier in the regular expression prevents newline injection attacks, ensuring complete remediation of the parameter parsing logic.
Exploitation of CVE-2026-84361 is straightforward if the victim's environment meets the prerequisites. The primary requirements are that the Perforce p4 command-line client is installed and accessible on the system's PATH, and the target executes a dependency resolution command on an untrusted configuration.
An attacker can trigger this vulnerability by publishing a malicious dependency within a custom package repository or by submitting a compromised composer.lock file to a repository. Below is an example of a malicious composer.json block that specifies a perforce repository type with an embedded command:
{
"type": "package",
"package": {
"name": "poc/perforce-source",
"version": "1.0.0",
"source": {
"type": "perforce",
"url": "rsh:touch /tmp/cve-2026-84361-composer-marker",
"reference": "//depot/main"
}
}
}When a developer or a continuous integration (CI) runner executes composer install or composer update --prefer-source, Composer parses this package definition. It attempts to verify the Perforce repository by executing p4 -p rsh:touch /tmp/... info -s. The p4 binary parses the rsh: transport scheme, spawns the sub-command, and triggers arbitrary command execution under the user's privilege level.
The impact of successful exploitation is critical, leading to full Remote Code Execution (RCE) on the host machine running Composer. In development environments, this grants the attacker access to local source code, environment variables, SSH keys, and local credentials.
In modern software engineering workflows, the impact on CI/CD pipelines is especially high. Automated systems frequently execute Composer commands as part of building, testing, or deploying applications. If a pipeline processes an untrusted pull request containing a malicious composer.lock file, the attacker can execute arbitrary commands on the build agent.
This execution can lead to compromised build artifacts, leaked cloud provider credentials, or secondary supply chain attacks if the build runner possesses write permissions to other repositories or container registries. The CVSS score of 7.7 reflects this risk, although the requirement for the p4 binary to be present on the host somewhat limits the default attack surface.
The primary and most effective remediation is upgrading Composer to a patched release. For legacy installations, the vulnerability is fixed in version 2.2.30. For modern environments, upgrading to 2.10.3 or later eliminates the flaw entirely.
If upgrading Composer is not immediately feasible, organizations should apply defensive mitigations to break the exploit chain. Since the exploit depends on the presence of the p4 command-line utility, removing the p4 binary from systems that do not use Perforce completely neutralizes the threat.
Additionally, team leads and security engineers should implement strict validation controls on package registries. Because Packagist.org does not permit Perforce source metadata, default public packages are safe. However, organizations hosting private registries should enforce schema validation to block the ingestion of any package containing a perforce source type with an unvalidated connection string.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Composer Composer Project | >= 1.0, < 2.2.30 | 2.2.30 |
Composer Composer Project | >= 2.3.0, < 2.10.3 | 2.10.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 |
| Attack Vector | Network |
| CVSS Score | 7.7 |
| EPSS Score | 0.00409 |
| Impact | Remote Code Execution (RCE) |
| Exploit Status | Proof-of-Concept (PoC) available |
| KEV Status | Not listed |
The software constructs an OS command using externally-influenced input, but it does not neutralize or incorrectly neutralize special elements that can modify the intended OS command when it is sent to a downstream component.
An authorization bypass vulnerability exists in the Astro web framework prior to version 7.2.4. When configured with a non-root base path, Astro's routing engine stripped the base path from incoming request URLs using an insecure prefix-match check without verifying path-segment boundaries. This created a path parser differential between user-defined middleware and the internal router. An unauthenticated attacker could bypass route-based authorization checks to access administrative or privileged endpoints by altering the path prefix segment.
A critical remote code execution vulnerability in Astro's image optimization pipeline allows unauthenticated attackers to trigger memory corruption via malformed AVIF images, due to outdated native dependencies in the sharp package.
A high-severity namespace injection vulnerability in both the MongoDB Client Library for PHP (mongodb/mongodb) and the native PHP C Extension (ext-mongodb) allows unauthenticated remote attackers to bypass logical database separation and execute database commands inside unauthorized storage compartments via dot (".") and null byte ("\0") injection.
A critical vulnerability (CVE-2026-84452) in the Windows ML CLI (winml-cli) HTTP server component allows unauthenticated remote code execution via permissive CORS and lack of request validation.
An incomplete fix vulnerability (CVE-2026-15603) in the morgan HTTP request logger middleware for Node.js allows unauthenticated remote attackers to forge log entries. The flaw arises because the escaping mechanism does not neutralize Unicode line separator characters, enabling attackers to inject payloads that trick downstream log processors into splitting single log records into multiple logical entries.
A high-severity denial of service vulnerability in the Node.js middleware 'multer' allows unauthenticated remote attackers to exhaust CPU resources and freeze applications. By submitting small, specially crafted 'multipart/form-data' requests containing large array indices alongside conflicting parameter keys, attackers force synchronous execution loops over up to 4.2 billion elements within the underlying 'append-field' library.