[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#988270: marked as done (unblock: composer/2.0.9-2)



Your message dated Sun, 09 May 2021 15:24:53 +0000
with message-id <E1lflIb-0005O1-HF@respighi.debian.org>
and subject line unblock composer
has caused the Debian Bug report #988270,
regarding unblock: composer/2.0.9-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
988270: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988270
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: carnil@debian.org,taffit@debian.org

Hi Release team,

Please unblock package composer

The update fixes CVE-2021-29472 (which was as well fixed in DSA 4907-1
for buster) and contains the security fix only (plus a change in the
Vcs-Git field).

unblock composer/composer

Regards,
Salvatore
diff -Nru composer-2.0.9/debian/changelog composer-2.0.9/debian/changelog
--- composer-2.0.9/debian/changelog	2021-01-29 01:05:13.000000000 +0100
+++ composer-2.0.9/debian/changelog	2021-04-28 00:20:52.000000000 +0200
@@ -1,3 +1,13 @@
+composer (2.0.9-2) unstable; urgency=medium
+
+  * Use debian/bullseye branch
+  * Security: Fixed command injection vulnerability.
+    Fix external process calls to avoid user input being able to pass extra
+    parameters in HgDriver/HgDownloader and hardened other VCS drivers and
+    downloaders (GHSA-h5h8-pc6h-jvvx) [CVE-2021-29472]
+
+ -- David Prévot <taffit@debian.org>  Tue, 27 Apr 2021 18:20:52 -0400
+
 composer (2.0.9-1) unstable; urgency=medium
 
   [ Jordi Boggiano ]
diff -Nru composer-2.0.9/debian/control composer-2.0.9/debian/control
--- composer-2.0.9/debian/control	2021-01-29 01:04:50.000000000 +0100
+++ composer-2.0.9/debian/control	2021-04-28 00:18:57.000000000 +0200
@@ -28,7 +28,7 @@
 Standards-Version: 4.5.1
 Homepage: https://getcomposer.org/
 Vcs-Browser: https://salsa.debian.org/php-team/pear/composer
-Vcs-Git: https://salsa.debian.org/php-team/pear/composer.git -b debian/latest
+Vcs-Git: https://salsa.debian.org/php-team/pear/composer.git -b debian/bullseye
 Rules-Requires-Root: no
 
 Package: composer
diff -Nru composer-2.0.9/debian/gbp.conf composer-2.0.9/debian/gbp.conf
--- composer-2.0.9/debian/gbp.conf	2021-01-28 23:53:16.000000000 +0100
+++ composer-2.0.9/debian/gbp.conf	2021-04-28 00:18:57.000000000 +0200
@@ -1,5 +1,5 @@
 [DEFAULT]
-debian-branch = debian/latest
+debian-branch = debian/bullseye
 pristine-tar = True
 filter = [ '.gitattributes' ]
 upstream-vcs-tag = %(version%~%-)s
diff -Nru composer-2.0.9/debian/patches/0009-Merge-pull-request-from-GHSA-h5h8-pc6h-jvvx.patch composer-2.0.9/debian/patches/0009-Merge-pull-request-from-GHSA-h5h8-pc6h-jvvx.patch
--- composer-2.0.9/debian/patches/0009-Merge-pull-request-from-GHSA-h5h8-pc6h-jvvx.patch	1970-01-01 01:00:00.000000000 +0100
+++ composer-2.0.9/debian/patches/0009-Merge-pull-request-from-GHSA-h5h8-pc6h-jvvx.patch	2021-04-28 00:18:57.000000000 +0200
@@ -0,0 +1,491 @@
+From: Jordi Boggiano <j.boggiano@seld.be>
+Date: Tue, 27 Apr 2021 13:00:40 +0200
+Subject: Merge pull request from GHSA-h5h8-pc6h-jvvx
+
+* Fix external process calls to avoid user input being able to pass extra parameters
+
+* Tweak some fixes
+
+Origin: upstream, https://github.com/composer/composer/commit/332c46af8bebdead80a2601350dff7af0ac1f490
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-29472
+---
+ src/Composer/Downloader/FossilDownloader.php       |  6 ++--
+ src/Composer/Downloader/GitDownloader.php          | 12 ++++----
+ src/Composer/Downloader/GzipDownloader.php         |  2 +-
+ src/Composer/Downloader/HgDownloader.php           |  6 ++--
+ src/Composer/Downloader/RarDownloader.php          |  2 +-
+ src/Composer/Downloader/SvnDownloader.php          |  2 +-
+ src/Composer/Repository/Vcs/FossilDriver.php       |  6 ++--
+ src/Composer/Repository/Vcs/GitDriver.php          |  2 +-
+ src/Composer/Repository/Vcs/HgDriver.php           |  4 +--
+ src/Composer/Repository/Vcs/SvnDriver.php          |  2 +-
+ src/Composer/Util/Git.php                          |  4 +--
+ src/Composer/Util/Svn.php                          |  2 +-
+ .../Test/Downloader/FossilDownloaderTest.php       |  6 ++--
+ .../Composer/Test/Downloader/GitDownloaderTest.php | 36 +++++++++++-----------
+ .../Composer/Test/Downloader/HgDownloaderTest.php  |  6 ++--
+ tests/Composer/Test/Util/SvnTest.php               |  2 +-
+ 16 files changed, 50 insertions(+), 50 deletions(-)
+
+diff --git a/src/Composer/Downloader/FossilDownloader.php b/src/Composer/Downloader/FossilDownloader.php
+index a597d51..74364dd 100644
+--- a/src/Composer/Downloader/FossilDownloader.php
++++ b/src/Composer/Downloader/FossilDownloader.php
+@@ -39,15 +39,15 @@ class FossilDownloader extends VcsDownloader
+         $ref = ProcessExecutor::escape($package->getSourceReference());
+         $repoFile = $path . '.fossil';
+         $this->io->writeError("Cloning ".$package->getSourceReference());
+-        $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
++        $command = sprintf('fossil clone -- %s %s', $url, ProcessExecutor::escape($repoFile));
+         if (0 !== $this->process->execute($command, $ignoredOutput)) {
+             throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+         }
+-        $command = sprintf('fossil open %s --nested', ProcessExecutor::escape($repoFile));
++        $command = sprintf('fossil open --nested -- %s', ProcessExecutor::escape($repoFile));
+         if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
+             throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+         }
+-        $command = sprintf('fossil update %s', $ref);
++        $command = sprintf('fossil update -- %s', $ref);
+         if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
+             throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+         }
+diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php
+index dd8a7d8..ef23a51 100644
+--- a/src/Composer/Downloader/GitDownloader.php
++++ b/src/Composer/Downloader/GitDownloader.php
+@@ -90,10 +90,10 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
+             $command =
+                 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
+                 . '&& cd '.$flag.'%path% '
+-                . '&& git remote set-url origin %sanitizedUrl% && git remote add composer %sanitizedUrl%';
++                . '&& git remote set-url origin -- %sanitizedUrl% && git remote add composer -- %sanitizedUrl%';
+         } else {
+             $msg = "Cloning ".$this->getShortHash($ref);
+-            $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer && git remote set-url origin %sanitizedUrl% && git remote set-url composer %sanitizedUrl%';
++            $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
+             if (getenv('COMPOSER_DISABLE_NETWORK')) {
+                 throw new \RuntimeException('The required git reference for '.$package->getName().' is not in cache and network is disabled, aborting');
+             }
+@@ -145,10 +145,10 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
+ 
+         if (!empty($this->cachedPackages[$target->getId()][$ref])) {
+             $msg = "Checking out ".$this->getShortHash($ref).' from cache';
+-            $command = '(git rev-parse --quiet --verify %ref% || (git remote set-url composer %cachePath% && git fetch composer && git fetch --tags composer)) && git remote set-url composer %sanitizedUrl%';
++            $command = '(git rev-parse --quiet --verify %ref% || (git remote set-url composer -- %cachePath% && git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
+         } else {
+             $msg = "Checking out ".$this->getShortHash($ref);
+-            $command = '(git remote set-url composer %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer %sanitizedUrl%';
++            $command = '(git remote set-url composer -- %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
+             if (getenv('COMPOSER_DISABLE_NETWORK')) {
+                 throw new \RuntimeException('The required git reference for '.$target->getName().' is not in cache and network is disabled, aborting');
+             }
+@@ -476,7 +476,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
+ 
+     protected function updateOriginUrl($path, $url)
+     {
+-        $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
++        $this->process->execute(sprintf('git remote set-url origin -- %s', ProcessExecutor::escape($url)), $output, $path);
+         $this->setPushUrl($path, $url);
+     }
+ 
+@@ -489,7 +489,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
+             if (!in_array('ssh', $protocols, true)) {
+                 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
+             }
+-            $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
++            $cmd = sprintf('git remote set-url --push origin -- %s', ProcessExecutor::escape($pushUrl));
+             $this->process->execute($cmd, $ignoredOutput, $path);
+         }
+     }
+diff --git a/src/Composer/Downloader/GzipDownloader.php b/src/Composer/Downloader/GzipDownloader.php
+index 04dd5e7..e12e091 100644
+--- a/src/Composer/Downloader/GzipDownloader.php
++++ b/src/Composer/Downloader/GzipDownloader.php
+@@ -30,7 +30,7 @@ class GzipDownloader extends ArchiveDownloader
+ 
+         // Try to use gunzip on *nix
+         if (!Platform::isWindows()) {
+-            $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
++            $command = 'gzip -cd -- ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
+ 
+             if (0 === $this->process->execute($command, $ignoredOutput)) {
+                 return;
+diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php
+index 59ced01..1997b31 100644
+--- a/src/Composer/Downloader/HgDownloader.php
++++ b/src/Composer/Downloader/HgDownloader.php
+@@ -36,13 +36,13 @@ class HgDownloader extends VcsDownloader
+         $hgUtils = new HgUtils($this->io, $this->config, $this->process);
+ 
+         $cloneCommand = function ($url) use ($path) {
+-            return sprintf('hg clone %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
++            return sprintf('hg clone -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
+         };
+ 
+         $hgUtils->runCommand($cloneCommand, $url, $path);
+ 
+         $ref = ProcessExecutor::escape($package->getSourceReference());
+-        $command = sprintf('hg up %s', $ref);
++        $command = sprintf('hg up -- %s', $ref);
+         if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
+             throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+         }
+@@ -63,7 +63,7 @@ class HgDownloader extends VcsDownloader
+         }
+ 
+         $command = function ($url) use ($ref) {
+-            return sprintf('hg pull %s && hg up %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
++            return sprintf('hg pull -- %s && hg up -- %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
+         };
+ 
+         $hgUtils->runCommand($command, $url, $path);
+diff --git a/src/Composer/Downloader/RarDownloader.php b/src/Composer/Downloader/RarDownloader.php
+index 8951d96..7f58922 100644
+--- a/src/Composer/Downloader/RarDownloader.php
++++ b/src/Composer/Downloader/RarDownloader.php
+@@ -33,7 +33,7 @@ class RarDownloader extends ArchiveDownloader
+ 
+         // Try to use unrar on *nix
+         if (!Platform::isWindows()) {
+-            $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
++            $command = 'unrar x -- ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
+ 
+             if (0 === $this->process->execute($command, $ignoredOutput)) {
+                 return;
+diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php
+index 2f253b4..d2e2adc 100644
+--- a/src/Composer/Downloader/SvnDownloader.php
++++ b/src/Composer/Downloader/SvnDownloader.php
+@@ -179,7 +179,7 @@ class SvnDownloader extends VcsDownloader
+     {
+         if (preg_match('{@(\d+)$}', $fromReference) && preg_match('{@(\d+)$}', $toReference)) {
+             // retrieve the svn base url from the checkout folder
+-            $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
++            $command = sprintf('svn info --non-interactive --xml -- %s', ProcessExecutor::escape($path));
+             if (0 !== $this->process->execute($command, $output, $path)) {
+                 throw new \RuntimeException(
+                     'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
+diff --git a/src/Composer/Repository/Vcs/FossilDriver.php b/src/Composer/Repository/Vcs/FossilDriver.php
+index 12218b2..8f73ffb 100644
+--- a/src/Composer/Repository/Vcs/FossilDriver.php
++++ b/src/Composer/Repository/Vcs/FossilDriver.php
+@@ -94,13 +94,13 @@ class FossilDriver extends VcsDriver
+ 
+             $fs->ensureDirectoryExists($this->checkoutDir);
+ 
+-            if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
++            if (0 !== $this->process->execute(sprintf('fossil clone -- %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
+                 $output = $this->process->getErrorOutput();
+ 
+                 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
+             }
+ 
+-            if (0 !== $this->process->execute(sprintf('fossil open %s --nested', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
++            if (0 !== $this->process->execute(sprintf('fossil open --nested -- %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
+                 $output = $this->process->getErrorOutput();
+ 
+                 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
+@@ -149,7 +149,7 @@ class FossilDriver extends VcsDriver
+      */
+     public function getFileContent($file, $identifier)
+     {
+-        $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
++        $command = sprintf('fossil cat -r %s -- %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
+         $this->process->execute($command, $content, $this->checkoutDir);
+ 
+         if (!trim($content)) {
+diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php
+index 3c3817c..70400e8 100644
+--- a/src/Composer/Repository/Vcs/GitDriver.php
++++ b/src/Composer/Repository/Vcs/GitDriver.php
+@@ -227,7 +227,7 @@ class GitDriver extends VcsDriver
+ 
+         try {
+             $gitUtil->runCommand(function ($url) {
+-                return 'git ls-remote --heads ' . ProcessExecutor::escape($url);
++                return 'git ls-remote --heads -- ' . ProcessExecutor::escape($url);
+             }, $url, sys_get_temp_dir());
+         } catch (\RuntimeException $e) {
+             return false;
+diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php
+index 4fa7371..f3b0e6c 100644
+--- a/src/Composer/Repository/Vcs/HgDriver.php
++++ b/src/Composer/Repository/Vcs/HgDriver.php
+@@ -67,7 +67,7 @@ class HgDriver extends VcsDriver
+ 
+                 $repoDir = $this->repoDir;
+                 $command = function ($url) use ($repoDir) {
+-                    return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
++                    return sprintf('hg clone --noupdate -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
+                 };
+ 
+                 $hgUtils->runCommand($command, $this->url, null);
+@@ -228,7 +228,7 @@ class HgDriver extends VcsDriver
+         }
+ 
+         $process = new ProcessExecutor($io);
+-        $exit = $process->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
++        $exit = $process->execute(sprintf('hg identify -- %s', ProcessExecutor::escape($url)), $ignored);
+ 
+         return $exit === 0;
+     }
+diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php
+index 8e2c5e7..ab3f95f 100644
+--- a/src/Composer/Repository/Vcs/SvnDriver.php
++++ b/src/Composer/Repository/Vcs/SvnDriver.php
+@@ -306,7 +306,7 @@ class SvnDriver extends VcsDriver
+ 
+         $process = new ProcessExecutor($io);
+         $exit = $process->execute(
+-            "svn info --non-interactive ".ProcessExecutor::escape($url),
++            "svn info --non-interactive -- ".ProcessExecutor::escape($url),
+             $ignoredOutput
+         );
+ 
+diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php
+index 6539693..312b5b0 100644
+--- a/src/Composer/Util/Git.php
++++ b/src/Composer/Util/Git.php
+@@ -261,7 +261,7 @@ class Git
+                 $commandCallable = function ($url) {
+                     $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url);
+ 
+-                    return sprintf('git remote set-url origin %s && git remote update --prune origin && git remote set-url origin %s && git gc --auto', ProcessExecutor::escape($url), ProcessExecutor::escape($sanitizedUrl));
++                    return sprintf('git remote set-url origin -- %s && git remote update --prune origin && git remote set-url origin -- %s && git gc --auto', ProcessExecutor::escape($url), ProcessExecutor::escape($sanitizedUrl));
+                 };
+                 $this->runCommand($commandCallable, $url, $dir);
+             } catch (\Exception $e) {
+@@ -277,7 +277,7 @@ class Git
+         $this->filesystem->removeDirectory($dir);
+ 
+         $commandCallable = function ($url) use ($dir) {
+-            return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
++            return sprintf('git clone --mirror -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
+         };
+ 
+         $this->runCommand($commandCallable, $url, $dir, true);
+diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php
+index 6088d0c..da934c1 100644
+--- a/src/Composer/Util/Svn.php
++++ b/src/Composer/Util/Svn.php
+@@ -224,7 +224,7 @@ class Svn
+     protected function getCommand($cmd, $url, $path = null)
+     {
+         $cmd = sprintf(
+-            '%s %s%s %s',
++            '%s %s%s -- %s',
+             $cmd,
+             '--non-interactive ',
+             $this->getCredentialString(),
+diff --git a/tests/Composer/Test/Downloader/FossilDownloaderTest.php b/tests/Composer/Test/Downloader/FossilDownloaderTest.php
+index dbd07cd..adf26c7 100644
+--- a/tests/Composer/Test/Downloader/FossilDownloaderTest.php
++++ b/tests/Composer/Test/Downloader/FossilDownloaderTest.php
+@@ -69,19 +69,19 @@ class FossilDownloaderTest extends TestCase
+             ->will($this->returnValue(array('http://fossil.kd2.org/kd2fw/')));
+         $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
+ 
+-        $expectedFossilCommand = $this->getCmd('fossil clone \'http://fossil.kd2.org/kd2fw/\' \'repo.fossil\'');
++        $expectedFossilCommand = $this->getCmd('fossil clone -- \'http://fossil.kd2.org/kd2fw/\' \'repo.fossil\'');
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedFossilCommand))
+             ->will($this->returnValue(0));
+ 
+-        $expectedFossilCommand = $this->getCmd('fossil open \'repo.fossil\' --nested');
++        $expectedFossilCommand = $this->getCmd('fossil open --nested -- \'repo.fossil\'');
+         $processExecutor->expects($this->at(1))
+             ->method('execute')
+             ->with($this->equalTo($expectedFossilCommand))
+             ->will($this->returnValue(0));
+ 
+-        $expectedFossilCommand = $this->getCmd('fossil update \'trunk\'');
++        $expectedFossilCommand = $this->getCmd('fossil update -- \'trunk\'');
+         $processExecutor->expects($this->at(2))
+             ->method('execute')
+             ->with($this->equalTo($expectedFossilCommand))
+diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php
+index e09b6d4..1a321c8 100644
+--- a/tests/Composer/Test/Downloader/GitDownloaderTest.php
++++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php
+@@ -109,7 +109,7 @@ class GitDownloaderTest extends TestCase
+             ->will($this->returnValue('dev-master'));
+         $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
+ 
+-        $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin 'https://example.com/composer/composer' && git remote set-url composer 'https://example.com/composer/composer'");
++        $expectedGitCommand = $this->winCompat("git clone --no-checkout -- 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin -- 'https://example.com/composer/composer' && git remote set-url composer -- 'https://example.com/composer/composer'");
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+@@ -158,7 +158,7 @@ class GitDownloaderTest extends TestCase
+         $filesystem = new \Composer\Util\Filesystem;
+         $filesystem->removeDirectory($cachePath);
+ 
+-        $expectedGitCommand = $this->winCompat(sprintf("git clone --mirror 'https://example.com/composer/composer' '%s'", $cachePath));
++        $expectedGitCommand = $this->winCompat(sprintf("git clone --mirror -- 'https://example.com/composer/composer' '%s'", $cachePath));
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+@@ -180,7 +180,7 @@ class GitDownloaderTest extends TestCase
+             ->with($this->equalTo($this->winCompat('git rev-parse --quiet --verify \'1234567890123456789012345678901234567890^{commit}\'')), $this->equalTo(null), $this->equalTo($this->winCompat($cachePath)))
+             ->will($this->returnValue(0));
+ 
+-        $expectedGitCommand = $this->winCompat(sprintf("git clone --no-checkout '%1\$s' 'composerPath' --dissociate --reference '%1\$s' && cd 'composerPath' && git remote set-url origin 'https://example.com/composer/composer' && git remote add composer 'https://example.com/composer/composer'", $cachePath));
++        $expectedGitCommand = $this->winCompat(sprintf("git clone --no-checkout '%1\$s' 'composerPath' --dissociate --reference '%1\$s' && cd 'composerPath' && git remote set-url origin -- 'https://example.com/composer/composer' && git remote add composer -- 'https://example.com/composer/composer'", $cachePath));
+         $processExecutor->expects($this->at(3))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+@@ -221,7 +221,7 @@ class GitDownloaderTest extends TestCase
+             ->will($this->returnValue('1.0.0'));
+         $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
+ 
+-        $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://github.com/mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://github.com/mirrors/composer' && git fetch composer && git remote set-url origin 'https://github.com/mirrors/composer' && git remote set-url composer 'https://github.com/mirrors/composer'");
++        $expectedGitCommand = $this->winCompat("git clone --no-checkout -- 'https://github.com/mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'https://github.com/mirrors/composer' && git fetch composer && git remote set-url origin -- 'https://github.com/mirrors/composer' && git remote set-url composer -- 'https://github.com/mirrors/composer'");
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+@@ -232,19 +232,19 @@ class GitDownloaderTest extends TestCase
+             ->with()
+             ->will($this->returnValue('Error1'));
+ 
+-        $expectedGitCommand = $this->winCompat("git clone --no-checkout 'git@github.com:mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'git@github.com:mirrors/composer' && git fetch composer && git remote set-url origin 'git@github.com:mirrors/composer' && git remote set-url composer 'git@github.com:mirrors/composer'");
++        $expectedGitCommand = $this->winCompat("git clone --no-checkout -- 'git@github.com:mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'git@github.com:mirrors/composer' && git fetch composer && git remote set-url origin -- 'git@github.com:mirrors/composer' && git remote set-url composer -- 'git@github.com:mirrors/composer'");
+         $processExecutor->expects($this->at(2))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+             ->will($this->returnValue(0));
+ 
+-        $expectedGitCommand = $this->winCompat("git remote set-url origin 'https://github.com/composer/composer'");
++        $expectedGitCommand = $this->winCompat("git remote set-url origin -- 'https://github.com/composer/composer'");
+         $processExecutor->expects($this->at(3))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
+             ->will($this->returnValue(0));
+ 
+-        $expectedGitCommand = $this->winCompat("git remote set-url --push origin 'git@github.com:composer/composer.git'");
++        $expectedGitCommand = $this->winCompat("git remote set-url --push origin -- 'git@github.com:composer/composer.git'");
+         $processExecutor->expects($this->at(4))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
+@@ -299,13 +299,13 @@ class GitDownloaderTest extends TestCase
+             ->will($this->returnValue('1.0.0'));
+         $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
+ 
+-        $expectedGitCommand = $this->winCompat("git clone --no-checkout '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer '{$url}' && git fetch composer && git remote set-url origin '{$url}' && git remote set-url composer '{$url}'");
++        $expectedGitCommand = $this->winCompat("git clone --no-checkout -- '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer -- '{$url}' && git fetch composer && git remote set-url origin -- '{$url}' && git remote set-url composer -- '{$url}'");
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+             ->will($this->returnValue(0));
+ 
+-        $expectedGitCommand = $this->winCompat("git remote set-url --push origin '{$pushUrl}'");
++        $expectedGitCommand = $this->winCompat("git remote set-url --push origin -- '{$pushUrl}'");
+         $processExecutor->expects($this->at(1))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
+@@ -327,7 +327,7 @@ class GitDownloaderTest extends TestCase
+ 
+     public function testDownloadThrowsRuntimeExceptionIfGitCommandFails()
+     {
+-        $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin 'https://example.com/composer/composer' && git remote set-url composer 'https://example.com/composer/composer'");
++        $expectedGitCommand = $this->winCompat("git clone --no-checkout -- 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin -- 'https://example.com/composer/composer' && git remote set-url composer -- 'https://example.com/composer/composer'");
+         $packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
+         $packageMock->expects($this->any())
+             ->method('getSourceReference')
+@@ -376,7 +376,7 @@ class GitDownloaderTest extends TestCase
+ 
+     public function testUpdate()
+     {
+-        $expectedGitUpdateCommand = $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'");
++        $expectedGitUpdateCommand = $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();
+         $packageMock->expects($this->any())
+@@ -407,7 +407,7 @@ class GitDownloaderTest extends TestCase
+ 
+     public function testUpdateWithNewRepoUrl()
+     {
+-        $expectedGitUpdateCommand = $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'");
++        $expectedGitUpdateCommand = $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();
+         $packageMock->expects($this->any())
+@@ -462,11 +462,11 @@ composer https://github.com/old/url (push)
+             }));
+         $processExecutor->expects($this->at(7))
+             ->method('execute')
+-            ->with($this->equalTo($this->winCompat("git remote set-url origin 'https://github.com/composer/composer'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
++            ->with($this->equalTo($this->winCompat("git remote set-url origin -- 'https://github.com/composer/composer'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
+             ->will($this->returnValue(0));
+         $processExecutor->expects($this->at(8))
+             ->method('execute')
+-            ->with($this->equalTo($this->winCompat("git remote set-url --push origin 'git@github.com:composer/composer.git'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
++            ->with($this->equalTo($this->winCompat("git remote set-url --push origin -- 'git@github.com:composer/composer.git'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
+             ->will($this->returnValue(0));
+ 
+         $this->fs->ensureDirectoryExists($this->workingDir.'/.git');
+@@ -482,8 +482,8 @@ composer https://github.com/old/url (push)
+      */
+     public function testUpdateThrowsRuntimeExceptionIfGitCommandFails()
+     {
+-        $expectedGitUpdateCommand = $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'");
+-        $expectedGitUpdateCommand2 = $this->winCompat("(git remote set-url composer 'git@github.com:composer/composer' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer 'git@github.com:composer/composer'");
++        $expectedGitUpdateCommand = $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'");
++        $expectedGitUpdateCommand2 = $this->winCompat("(git remote set-url composer -- 'git@github.com:composer/composer' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- 'git@github.com:composer/composer'");
+ 
+         $packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
+         $packageMock->expects($this->any())
+@@ -526,8 +526,8 @@ composer https://github.com/old/url (push)
+ 
+     public function testUpdateDoesntThrowsRuntimeExceptionIfGitCommandFailsAtFirstButIsAbleToRecover()
+     {
+-        $expectedFirstGitUpdateCommand = $this->winCompat("(git remote set-url composer '".(Platform::isWindows() ? 'C:\\\\' : '/')."' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer '".(Platform::isWindows() ? 'C:\\\\' : '/')."'");
+-        $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'");
++        $expectedFirstGitUpdateCommand = $this->winCompat("(git remote set-url composer -- '".(Platform::isWindows() ? 'C:\\\\' : '/')."' && git rev-parse --quiet --verify 'ref^{commit}' || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- '".(Platform::isWindows() ? 'C:\\\\' : '/')."'");
++        $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();
+         $packageMock->expects($this->any())
+diff --git a/tests/Composer/Test/Downloader/HgDownloaderTest.php b/tests/Composer/Test/Downloader/HgDownloaderTest.php
+index 64f72d1..14afdcf 100644
+--- a/tests/Composer/Test/Downloader/HgDownloaderTest.php
++++ b/tests/Composer/Test/Downloader/HgDownloaderTest.php
+@@ -69,13 +69,13 @@ class HgDownloaderTest extends TestCase
+             ->will($this->returnValue(array('https://mercurial.dev/l3l0/composer')));
+         $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
+ 
+-        $expectedGitCommand = $this->getCmd('hg clone \'https://mercurial.dev/l3l0/composer\' \'composerPath\'');
++        $expectedGitCommand = $this->getCmd('hg clone -- \'https://mercurial.dev/l3l0/composer\' \'composerPath\'');
+         $processExecutor->expects($this->at(0))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+             ->will($this->returnValue(0));
+ 
+-        $expectedGitCommand = $this->getCmd('hg up \'ref\'');
++        $expectedGitCommand = $this->getCmd('hg up -- \'ref\'');
+         $processExecutor->expects($this->at(1))
+             ->method('execute')
+             ->with($this->equalTo($expectedGitCommand))
+@@ -122,7 +122,7 @@ class HgDownloaderTest extends TestCase
+             ->method('execute')
+             ->with($this->equalTo($expectedHgCommand))
+             ->will($this->returnValue(0));
+-        $expectedHgCommand = $this->getCmd("hg pull 'https://github.com/l3l0/composer' && hg up 'ref'");
++        $expectedHgCommand = $this->getCmd("hg pull -- 'https://github.com/l3l0/composer' && hg up -- 'ref'");
+         $processExecutor->expects($this->at(1))
+             ->method('execute')
+             ->with($this->equalTo($expectedHgCommand))
+diff --git a/tests/Composer/Test/Util/SvnTest.php b/tests/Composer/Test/Util/SvnTest.php
+index 03a1835..ada3818 100644
+--- a/tests/Composer/Test/Util/SvnTest.php
++++ b/tests/Composer/Test/Util/SvnTest.php
+@@ -60,7 +60,7 @@ class SvnTest extends TestCase
+         $reflMethod->setAccessible(true);
+ 
+         $this->assertEquals(
+-            $this->getCmd("svn ls --non-interactive  'http://svn.example.org'"),
++            $this->getCmd("svn ls --non-interactive  -- 'http://svn.example.org'"),
+             $reflMethod->invokeArgs($svn, array('svn ls', $url))
+         );
+     }
diff -Nru composer-2.0.9/debian/patches/series composer-2.0.9/debian/patches/series
--- composer-2.0.9/debian/patches/series	2021-01-28 23:53:35.000000000 +0100
+++ composer-2.0.9/debian/patches/series	2021-04-28 00:18:57.000000000 +0200
@@ -6,3 +6,4 @@
 0007-Tag-test-relying-on-git-repository.patch
 0007-Use-expectException-instead-of-setExpectedException.patch
 0008-Compatibility-with-recent-PHPUnit-8.patch
+0009-Merge-pull-request-from-GHSA-h5h8-pc6h-jvvx.patch

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: