CVE-2021-41116 Overview
CVE-2021-41116 is a command injection vulnerability affecting Composer, the widely-used open source dependency manager for the PHP programming language. This vulnerability specifically impacts Windows users who run Composer to install untrusted dependencies. The flaw allows attackers to inject arbitrary commands through specially crafted package metadata, potentially leading to full system compromise. Other operating systems, including Linux, macOS, and Windows Subsystem for Linux (WSL), are not affected by this vulnerability.
Critical Impact
Windows users running Composer with untrusted dependencies are subject to command injection attacks that could result in arbitrary code execution with the privileges of the Composer process, potentially allowing complete system compromise.
Affected Products
- Getcomposer Composer versions prior to 1.10.23
- Getcomposer Composer versions 2.x prior to 2.1.9
- Tenable Tenable.sc (which bundles affected Composer versions)
Discovery Timeline
- 2021-10-05 - CVE-2021-41116 published to NVD
- 2024-11-21 - Last updated in NVD database
Technical Details for CVE-2021-41116
Vulnerability Analysis
This command injection vulnerability stems from improper handling of shell arguments when Composer executes external processes on Windows systems. The flaw exists in the way Composer constructs shell commands, particularly when opening URLs using the Windows explorer command. The vulnerability is classified under CWE-77 (Command Injection), indicating that user-controllable input is being incorporated into a command string without proper sanitization.
When a user runs Composer to install dependencies from an untrusted source, a malicious package could provide specially crafted URLs or metadata that, when processed by Composer's HomeCommand.php, would break out of the intended command context and execute arbitrary commands on the victim's system.
Root Cause
The root cause of this vulnerability lies in the improper escaping of shell arguments on Windows systems within two key components:
HomeCommand.php: The code incorrectly wrapped the URL parameter in double quotes when executing the Windows explorer command, creating an injection point.
ProcessExecutor.php: The argument escaping function contained Windows-specific logic that attempted to work around PHP bugs related to escapeshellarg(), but this custom implementation introduced security weaknesses.
The flawed escaping logic failed to properly neutralize special characters that have meaning to the Windows command interpreter, allowing command injection through carefully crafted input strings.
Attack Vector
The attack is network-based and requires no authentication or user interaction beyond the normal workflow of installing dependencies. An attacker could:
- Create a malicious Composer package with specially crafted metadata
- Host the package on a public repository or compromise an existing package
- When a Windows user installs or interacts with this package, the injected commands execute
The following patch from the Composer repository shows how the vulnerability was addressed in HomeCommand.php:
$process = new ProcessExecutor($this->getIO());
if (Platform::isWindows()) {
- return $process->execute('start "web" explorer "' . $url . '"', $output);
+ return $process->execute('start "web" explorer ' . $url, $output);
}
$linux = $process->execute('which xdg-open', $output);
Source: GitHub Commit Update
The second patch in ProcessExecutor.php replaced the custom Windows escaping logic with Symfony's proven Process::escapeArgument() implementation:
}
/**
- * Copy of ProcessUtils::escapeArgument() that is deprecated in Symfony 3.3 and removed in Symfony 4.
+ * Copy of Symfony's Process::escapeArgument() which is private
*
* @param string $argument
*
* @return string
*/
private static function escapeArgument($argument)
{
- //Fix for PHP bug #43784 escapeshellarg removes % from given string
- //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
- //@see https://bugs.php.net/bug.php?id=43784
- //@see https://bugs.php.net/bug.php?id=49446
- if ('\\' === DIRECTORY_SEPARATOR) {
- if ((string) $argument === '') {
- return escapeshellarg($argument);
- }
-
- $escapedArgument = '';
- $quote = false;
- foreach (preg_split('/("/)/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
- if ('"' === $part) {
- $escapedArgument .= '\\"';
- } elseif (self::isSurroundedBy($part, '%')) {
- // Avoid environment variable expansion
- $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
- } else {
Source: GitHub Commit Update
Detection Methods for CVE-2021-41116
Indicators of Compromise
- Unexpected child processes spawned from php.exe or composer.phar on Windows systems
- Unusual commands executed via the Windows explorer command or cmd.exe
- Network connections to unknown external hosts originating from Composer processes
- Suspicious entries in Windows Event Logs showing command-line executions with encoded or obfuscated parameters
Detection Strategies
- Monitor for process creation events where explorer.exe is spawned with unusual or encoded command-line arguments
- Implement application allowlisting to detect unauthorized executables launched during package installation
- Use endpoint detection tools to identify command injection patterns in shell executions
- Review Composer logs for suspicious package URLs or metadata during dependency installation
Monitoring Recommendations
- Enable verbose logging for Composer operations using composer -vvv to capture detailed execution information
- Configure Windows Security Event auditing for process creation (Event ID 4688) with command-line logging enabled
- Deploy behavioral analysis tools to detect anomalous process trees originating from PHP or Composer processes
- Regularly audit installed Composer packages against known vulnerability databases
How to Mitigate CVE-2021-41116
Immediate Actions Required
- Upgrade Composer to version 1.10.23 or later for the 1.x branch
- Upgrade Composer to version 2.1.9 or later for the 2.x branch
- Avoid installing packages from untrusted sources until patched
- Review recently installed packages for potential compromise if running vulnerable versions on Windows
Patch Information
The vulnerability has been resolved in Composer versions 1.10.23 and 2.1.9. The fix involves removing the problematic double-quote wrapping around URLs in the Windows explorer command execution and replacing the custom argument escaping function with Symfony's secure implementation.
Users can update Composer using the self-update command or by downloading the latest version from the official Composer website. The security fix is detailed in the GitHub Security Advisory GHSA-frqg-7g38-6gcf and the commit that addresses the vulnerability.
Workarounds
- There are no official workarounds for this vulnerability; upgrading is the only mitigation
- Consider running Composer in a non-Windows environment (Linux, macOS, or WSL) until patching is complete
- Implement strict package source policies to only allow dependencies from trusted repositories
- Use network segmentation to limit the impact of potential command execution on development workstations
# Upgrade Composer to the latest secure version
composer self-update --2
# Verify the installed version is patched
composer --version
# Should show 2.1.9 or later for 2.x branch, or 1.10.23 or later for 1.x branch
# Alternative: Download specific patched version
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --version=2.1.9
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


