Version in base suite: 2.5.5-1+deb12u3 Base version: composer_2.5.5-1+deb12u3 Target version: composer_2.5.5-1+deb12u4 Base file: /srv/ftp-master.debian.org/ftp/pool/main/c/composer/composer_2.5.5-1+deb12u3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/c/composer/composer_2.5.5-1+deb12u4.dsc changelog | 11 patches/0019-Merge-commit-from-fork.patch | 47 + patches/0020-Merge-commit-from-fork.patch | 236 ++++++++++ patches/0021-Merge-pull-request-from-GHSA-jm6m-4632-36hf.patch | 27 + patches/series | 3 5 files changed, 324 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpds51oics/composer_2.5.5-1+deb12u3.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpds51oics/composer_2.5.5-1+deb12u4.dsc: no acceptable signature found diff -Nru composer-2.5.5/debian/changelog composer-2.5.5/debian/changelog --- composer-2.5.5/debian/changelog 2025-12-30 16:01:22.000000000 +0000 +++ composer-2.5.5/debian/changelog 2026-04-15 10:33:06.000000000 +0000 @@ -1,3 +1,14 @@ +composer (2.5.5-1+deb12u4) bookworm; urgency=medium + + * Fix command injection via malicious Perforce source reference/url + [CVE-2026-40261] + * Fix ommand injection via malicious Perforce repository definition + [CVE-2026-40176] + * Fix remote Code Execution via web-accessible composer.phar + [CVE-2023-43655] + + -- David Prévot Wed, 15 Apr 2026 12:33:06 +0200 + composer (2.5.5-1+deb12u3) bookworm; urgency=medium * Backport fix from composer 2.2.26: diff -Nru composer-2.5.5/debian/patches/0019-Merge-commit-from-fork.patch composer-2.5.5/debian/patches/0019-Merge-commit-from-fork.patch --- composer-2.5.5/debian/patches/0019-Merge-commit-from-fork.patch 1970-01-01 00:00:00.000000000 +0000 +++ composer-2.5.5/debian/patches/0019-Merge-commit-from-fork.patch 2026-04-15 10:33:06.000000000 +0000 @@ -0,0 +1,47 @@ +From: Jordi Boggiano +Date: Tue, 14 Apr 2026 10:34:08 +0200 +Subject: Merge commit from fork + +Origin: upstream, https://github.com/composer/composer/commit/91f077050c13e49e22554b991c81378ce8b5ee16 +Bug: https://github.com/composer/composer/security/advisories/GHSA-gqw4-4w2p-838q +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-40261 +--- + src/Composer/Util/Perforce.php | 2 +- + tests/Composer/Test/Util/PerforceTest.php | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php +index d24209a..4ca0f8c 100644 +--- a/src/Composer/Util/Perforce.php ++++ b/src/Composer/Util/Perforce.php +@@ -353,7 +353,7 @@ class Perforce + chdir($this->path); + $p4SyncCommand = $this->generateP4Command('sync -f '); + if (null !== $sourceReference) { +- $p4SyncCommand .= '@' . $sourceReference; ++ $p4SyncCommand .= ProcessExecutor::escape('@' . $sourceReference); + } + $this->executeCommand($p4SyncCommand); + chdir($prevDir); +diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php +index 6fd37e5..c81d729 100644 +--- a/tests/Composer/Test/Util/PerforceTest.php ++++ b/tests/Composer/Test/Util/PerforceTest.php +@@ -539,7 +539,7 @@ class PerforceTest extends TestCase + public function testSyncCodeBaseWithoutStream(): void + { + $this->processExecutor->expects( +- ['p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label'], ++ ['p4 -u user -c composer_perforce_TEST_depot -p port sync -f \'@label\''], + true + ); + +@@ -551,7 +551,7 @@ class PerforceTest extends TestCase + $this->setPerforceToStream(); + + $this->processExecutor->expects( +- ['p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label'], ++ ['p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f \'@label\''], + true + ); + diff -Nru composer-2.5.5/debian/patches/0020-Merge-commit-from-fork.patch composer-2.5.5/debian/patches/0020-Merge-commit-from-fork.patch --- composer-2.5.5/debian/patches/0020-Merge-commit-from-fork.patch 1970-01-01 00:00:00.000000000 +0000 +++ composer-2.5.5/debian/patches/0020-Merge-commit-from-fork.patch 2026-04-15 10:33:06.000000000 +0000 @@ -0,0 +1,236 @@ +From: Jordi Boggiano +Date: Tue, 14 Apr 2026 10:41:57 +0200 +Subject: Merge commit from fork + +Co-authored-by: Stephan Vock + +Origin: backport, https://github.com/composer/composer/commit/4f02616e6fba3b1baf8d45725f847841b44fc15c +Bug: https://github.com/composer/composer/security/advisories/GHSA-wg36-wvj6-r67p +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-40176 +--- + src/Composer/Util/Perforce.php | 6 +-- + tests/Composer/Test/Util/PerforceTest.php | 82 ++++++++++++++++++++++++------- + 2 files changed, 67 insertions(+), 21 deletions(-) + +diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php +index 4ca0f8c..99d1a42 100644 +--- a/src/Composer/Util/Perforce.php ++++ b/src/Composer/Util/Perforce.php +@@ -310,11 +310,11 @@ class Perforce + public function generateP4Command(string $command, bool $useClient = true): string + { + $p4Command = 'p4 '; +- $p4Command .= '-u ' . $this->getUser() . ' '; ++ $p4Command .= '-u ' . ProcessExecutor::escape($this->getUser()) . ' '; + if ($useClient) { +- $p4Command .= '-c ' . $this->getClient() . ' '; ++ $p4Command .= '-c ' . ProcessExecutor::escape($this->getClient()) . ' '; + } +- $p4Command .= '-p ' . $this->getPort() . ' ' . $command; ++ $p4Command .= '-p ' . ProcessExecutor::escape($this->getPort()) . ' ' . $command; + + return $p4Command; + } +diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php +index c81d729..98a6965 100644 +--- a/tests/Composer/Test/Util/PerforceTest.php ++++ b/tests/Composer/Test/Util/PerforceTest.php +@@ -128,10 +128,56 @@ class PerforceTest extends TestCase + { + $command = 'do something'; + $p4Command = $this->perforce->generateP4Command($command); +- $expected = 'p4 -u user -c composer_perforce_TEST_depot -p port do something'; ++ $expected = "p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' do something"; + $this->assertEquals($expected, $p4Command); + } + ++ public function testGenerateP4CommandEscapesPortInjection(): void ++ { ++ $perforce = new Perforce( ++ ['depot' => 'depot', 'branch' => 'branch', 'p4user' => 'user', 'unique_perforce_client_name' => 'TEST'], ++ 'localhost:1666; touch /tmp/pwned', ++ 'path', ++ $this->processExecutor, ++ false, ++ $this->io ++ ); ++ $command = $perforce->generateP4Command('login -s', false); ++ self::assertStringNotContainsString('-p localhost:1666; touch /tmp/pwned', $command); ++ self::assertStringContainsString('-p '.ProcessExecutor::escape('localhost:1666; touch /tmp/pwned'), $command); ++ } ++ ++ public function testGenerateP4CommandEscapesUserInjection(): void ++ { ++ $perforce = new Perforce( ++ ['depot' => 'depot', 'branch' => 'branch', 'p4user' => 'user; id', 'unique_perforce_client_name' => 'TEST'], ++ 'port', ++ 'path', ++ $this->processExecutor, ++ false, ++ $this->io ++ ); ++ $command = $perforce->generateP4Command('login -s', false); ++ self::assertStringNotContainsString('-u user; id', $command); ++ self::assertStringContainsString('-u '.ProcessExecutor::escape('user; id'), $command); ++ } ++ ++ public function testGenerateP4CommandEscapesClientInjection(): void ++ { ++ $perforce = new Perforce( ++ ['depot' => 'foo; id #', 'branch' => 'branch', 'p4user' => 'user', 'unique_perforce_client_name' => 'TEST'], ++ 'port', ++ 'path', ++ $this->processExecutor, ++ false, ++ $this->io ++ ); ++ $command = $perforce->generateP4Command('do something'); ++ $expectedClient = 'composer_perforce_TEST_foo; id #'; ++ self::assertStringNotContainsString('-c '.$expectedClient.' ', $command); ++ self::assertStringContainsString('-c '.ProcessExecutor::escape($expectedClient), $command); ++ } ++ + public function testQueryP4UserWithUserAlreadySet(): void + { + $this->perforce->queryP4user(); +@@ -319,7 +365,7 @@ class PerforceTest extends TestCase + public function testIsLoggedIn(): void + { + $this->processExecutor->expects( +- [['cmd' => 'p4 -u user -p port login -s']], ++ [['cmd' => "p4 -u 'user' -p 'port' login -s"]], + true + ); + $this->perforce->isLoggedIn(); +@@ -328,7 +374,7 @@ class PerforceTest extends TestCase + public function testConnectClient(): void + { + $this->processExecutor->expects( +- ['p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec'], ++ ["p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' client -i < path/composer_perforce_TEST_depot.p4.spec"], + true + ); + +@@ -342,11 +388,11 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot_branch -p port streams '.ProcessExecutor::escape('//depot/...'), ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot_branch' -p 'port' streams ".ProcessExecutor::escape('//depot/...'), + 'stdout' => 'Stream //depot/branch mainline none \'branch\'' . PHP_EOL, + ], + [ +- 'cmd' => 'p4 -u user -p port changes '.ProcessExecutor::escape('//depot/branch/...'), ++ 'cmd' => "p4 -u 'user' -p 'port' changes ".ProcessExecutor::escape('//depot/branch/...'), + 'stdout' => 'Change 1234 on 2014/03/19 by Clark.Stuth@Clark.Stuth_test_client \'test changelist\'', + ], + ], +@@ -362,7 +408,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -p port changes '.ProcessExecutor::escape('//depot/...'), ++ 'cmd' => "p4 -u 'user' -p 'port' changes ".ProcessExecutor::escape('//depot/...'), + 'stdout' => 'Change 5678 on 2014/03/19 by Clark.Stuth@Clark.Stuth_test_client \'test changelist\'', + ], + ], +@@ -378,7 +424,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot -p port labels', ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' labels", + 'stdout' => 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL, + ], + ], +@@ -397,7 +443,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot_branch -p port labels', ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot_branch' -p 'port' labels", + 'stdout' => 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL, + ], + ], +@@ -421,7 +467,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -p port depots', ++ 'cmd' => "p4 -u 'user' -p 'port' depots", + 'stdout' => 'Depot depot 2013/06/25 stream /p4/1/depots/depot/... \'Created by Me\'', + ], + ], +@@ -438,7 +484,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot -p port print '.ProcessExecutor::escape('//depot/composer.json'), ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' print ".ProcessExecutor::escape('//depot/composer.json'), + 'stdout' => PerforceTest::getComposerJson(), + ], + ], +@@ -460,11 +506,11 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -p port files '.ProcessExecutor::escape('//depot/composer.json@0.0.1'), ++ 'cmd' => "p4 -u 'user' -p 'port' files ".ProcessExecutor::escape('//depot/composer.json@0.0.1'), + 'stdout' => '//depot/composer.json#1 - branch change 10001 (text)', + ], + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot -p port print '.ProcessExecutor::escape('//depot/composer.json@10001'), ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' print ".ProcessExecutor::escape('//depot/composer.json@10001'), + 'stdout' => PerforceTest::getComposerJson(), + ], + ], +@@ -489,7 +535,7 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print '.ProcessExecutor::escape('//depot/branch/composer.json'), ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot_branch' -p 'port' print ".ProcessExecutor::escape('//depot/branch/composer.json'), + 'stdout' => PerforceTest::getComposerJson(), + ], + ], +@@ -512,11 +558,11 @@ class PerforceTest extends TestCase + $this->processExecutor->expects( + [ + [ +- 'cmd' => 'p4 -u user -p port files '.ProcessExecutor::escape('//depot/branch/composer.json@0.0.1'), ++ 'cmd' => "p4 -u 'user' -p 'port' files ".ProcessExecutor::escape('//depot/branch/composer.json@0.0.1'), + 'stdout' => '//depot/composer.json#1 - branch change 10001 (text)', + ], + [ +- 'cmd' => 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print '.ProcessExecutor::escape('//depot/branch/composer.json@10001'), ++ 'cmd' => "p4 -u 'user' -c 'composer_perforce_TEST_depot_branch' -p 'port' print ".ProcessExecutor::escape('//depot/branch/composer.json@10001'), + 'stdout' => PerforceTest::getComposerJson(), + ], + ], +@@ -539,7 +585,7 @@ class PerforceTest extends TestCase + public function testSyncCodeBaseWithoutStream(): void + { + $this->processExecutor->expects( +- ['p4 -u user -c composer_perforce_TEST_depot -p port sync -f \'@label\''], ++ ["p4 -u 'user' -c 'composer_perforce_TEST_depot' -p 'port' sync -f '@label'"], + true + ); + +@@ -551,7 +597,7 @@ class PerforceTest extends TestCase + $this->setPerforceToStream(); + + $this->processExecutor->expects( +- ['p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f \'@label\''], ++ ["p4 -u 'user' -c 'composer_perforce_TEST_depot_branch' -p 'port' sync -f '@label'"], + true + ); + +@@ -647,7 +693,7 @@ class PerforceTest extends TestCase + + $testClient = $this->perforce->getClient(); + $this->processExecutor->expects( +- ['p4 -u ' . self::TEST_P4USER . ' -p ' . self::TEST_PORT . ' client -d ' . ProcessExecutor::escape($testClient)], ++ ["p4 -u '" . self::TEST_P4USER . "' -p '" . self::TEST_PORT . "' client -d " . ProcessExecutor::escape($testClient)], + true + ); + diff -Nru composer-2.5.5/debian/patches/0021-Merge-pull-request-from-GHSA-jm6m-4632-36hf.patch composer-2.5.5/debian/patches/0021-Merge-pull-request-from-GHSA-jm6m-4632-36hf.patch --- composer-2.5.5/debian/patches/0021-Merge-pull-request-from-GHSA-jm6m-4632-36hf.patch 1970-01-01 00:00:00.000000000 +0000 +++ composer-2.5.5/debian/patches/0021-Merge-pull-request-from-GHSA-jm6m-4632-36hf.patch 2026-04-15 10:33:06.000000000 +0000 @@ -0,0 +1,27 @@ +From: Jordi Boggiano +Date: Fri, 29 Sep 2023 10:15:51 +0200 +Subject: Merge pull request from GHSA-jm6m-4632-36hf + +Origin: upstream, https://github.com/composer/composer/commit/955a48e6319c8962e5cd421b07c00ab3c728968c +Bug: https://github.com/composer/composer/security/advisories/GHSA-jm6m-4632-36hf +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-43655 +--- + bin/composer | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/bin/composer b/bin/composer +index 238e669..ded411f 100755 +--- a/bin/composer ++++ b/bin/composer +@@ -2,6 +2,11 @@ +