High severityNVD Advisory· Published Oct 5, 2021· Updated Aug 4, 2024
Command injection in composer on Windows
CVE-2021-41116
Description
Composer is an open source dependency manager for the PHP language. In affected versions windows users running Composer to install untrusted dependencies are subject to command injection and should upgrade their composer version. Other OSs and WSL are not affected. The issue has been resolved in composer versions 1.10.23 and 2.1.9. There are no workarounds for this issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
composer/composerPackagist | < 1.10.23 | 1.10.23 |
composer/composerPackagist | >= 2.0.0-alpha1, < 2.1.9 | 2.1.9 |
Affected products
1Patches
1ca5e2f8d505fFix escaping issues on Windows which could lead to command injection, fixes GHSA-frqg-7g38-6gcf
5 files changed · +22 −36
CHANGELOG.md+5 −0 modified@@ -1,3 +1,7 @@ +### [1.10.23] 2021-10-05 + + * Security: Fixed command injection vulnerability on Windows (GHSA-frqg-7g38-6gcf / CVE-2021-41116) + ### [1.10.22] 2021-04-27 * Security: Fixed command injection vulnerability in HgDriver/HgDownloader and hardened other VCS drivers and downloaders (GHSA-h5h8-pc6h-jvvx / CVE-2021-29472) @@ -938,6 +942,7 @@ * Initial release +[1.10.23]: https://github.com/composer/composer/compare/1.10.22...1.10.23 [1.10.22]: https://github.com/composer/composer/compare/1.10.21...1.10.22 [1.10.21]: https://github.com/composer/composer/compare/1.10.20...1.10.21 [1.10.20]: https://github.com/composer/composer/compare/1.10.19...1.10.20
src/Composer/Command/HomeCommand.php+1 −1 modified@@ -129,7 +129,7 @@ private function openBrowser($url) $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);
src/Composer/Util/ProcessExecutor.php+14 −33 modified@@ -155,48 +155,29 @@ public static function escape($argument) } /** - * 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 { - // escape trailing backslash - if ('\\' === substr($part, -1)) { - $part .= '\\'; - } - $quote = true; - $escapedArgument .= $part; - } - } - if ($quote) { - $escapedArgument = '"'.$escapedArgument.'"'; - } - - return $escapedArgument; + if ('' === $argument || null === $argument) { + return '""'; + } + if ('\\' !== \DIRECTORY_SEPARATOR) { + return "'".str_replace("'", "'\\''", $argument)."'"; + } + if (false !== strpos($argument, "\0")) { + $argument = str_replace("\0", '?', $argument); + } + if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { + return $argument; } + $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); - return "'".str_replace("'", "'\\''", $argument)."'"; + return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"'; } private static function isSurroundedBy($arg, $char)
tests/Composer/Test/Downloader/GitDownloaderTest.php+1 −1 modified@@ -524,7 +524,7 @@ public function testUpdateThrowsRuntimeExceptionIfGitCommandFails() public function testUpdateDoesntThrowsRuntimeExceptionIfGitCommandFailsAtFirstButIsAbleToRecover() { - $expectedFirstGitUpdateCommand = $this->winCompat("(git remote set-url composer -- '' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- ''"); + $expectedFirstGitUpdateCommand = $this->winCompat("(git remote set-url composer -- \"\" && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- \"\""); $expectedSecondGitUpdateCommand = $this->winCompat("(git remote set-url composer -- 'https://github.com/composer/composer' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- 'https://github.com/composer/composer'"); $packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
tests/Composer/Test/Util/SvnTest.php+1 −1 modified@@ -47,7 +47,7 @@ public function urlProvider() return array( array('http://till:test@svn.example.org/', $this->getCmd(" --username 'till' --password 'test' ")), array('http://svn.apache.org/', ''), - array('svn://johndoe@example.org', $this->getCmd(" --username 'johndoe' --password '' ")), + array('svn://johndoe@example.org', $this->getCmd(" --username 'johndoe' --password \"\" ")), ); }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-frqg-7g38-6gcfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-41116ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/composer/composer/CVE-2021-41116.yamlghsaWEB
- github.com/composer/composer/commit/ca5e2f8d505fd3bfac6f7c85b82f2740becbc0aaghsax_refsource_MISCWEB
- github.com/composer/composer/security/advisories/GHSA-frqg-7g38-6gcfghsax_refsource_CONFIRMWEB
- www.sonarsource.com/blog/securing-developer-tools-package-managersghsaWEB
- www.sonarsource.com/blog/securing-developer-tools-package-managers/mitrex_refsource_MISC
- www.tenable.com/security/tns-2022-09ghsaWEB
News mentions
0No linked articles in our index yet.