Your message dated Sat, 10 Jan 2026 11:52:34 +0000
with message-id <[email protected]>
and subject line Released with 13.3
has caused the Debian Bug report #1124354,
regarding trixie-pu: package composer/2.8.8-1+deb13u1
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 [email protected]
immediately.)


-- 
1124354: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124354
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:composer
User: [email protected]
Usertags: pu

Hi,

As agreed with the security team, I’d like to fix CVE-2025-67746 in a
point release rather than a DSA since it mostly fixes a display issue.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

Regards,

taffit
diff -Nru composer-2.8.8/debian/changelog composer-2.8.8/debian/changelog
--- composer-2.8.8/debian/changelog	2025-04-05 11:50:09.000000000 +0200
+++ composer-2.8.8/debian/changelog	2025-12-30 16:35:23.000000000 +0100
@@ -1,3 +1,11 @@
+composer (2.8.8-1+deb13u1) trixie; urgency=medium
+
+  * Backport fix from composer 2.9.3:
+    Fixed ANSI sequence injection [CVE-2025-67746]
+  * Track debian/trixie
+
+ -- David Prévot <[email protected]>  Tue, 30 Dec 2025 16:35:23 +0100
+
 composer (2.8.8-1) unstable; urgency=medium
 
   [ Jordi Boggiano ]
diff -Nru composer-2.8.8/debian/gbp.conf composer-2.8.8/debian/gbp.conf
--- composer-2.8.8/debian/gbp.conf	2024-06-25 07:54:44.000000000 +0200
+++ composer-2.8.8/debian/gbp.conf	2025-12-30 16:35:07.000000000 +0100
@@ -1,5 +1,5 @@
 [DEFAULT]
-debian-branch = debian/latest
+debian-branch = debian/trixie
 filter = [ '.gitattributes' ]
 pristine-tar = True
 upstream-vcs-tag = %(version%~%-)s
diff -Nru composer-2.8.8/debian/patches/0017-Merge-commit-from-fork.patch composer-2.8.8/debian/patches/0017-Merge-commit-from-fork.patch
--- composer-2.8.8/debian/patches/0017-Merge-commit-from-fork.patch	1970-01-01 01:00:00.000000000 +0100
+++ composer-2.8.8/debian/patches/0017-Merge-commit-from-fork.patch	2025-12-30 16:33:32.000000000 +0100
@@ -0,0 +1,355 @@
+From: Jordi Boggiano <[email protected]>
+Date: Tue, 30 Dec 2025 13:18:16 +0100
+Subject: Merge commit from fork
+
+Origin: upstream, https://github.com/composer/composer/commit/5db1876a76fdef76d3c4f8a27995c434c7a43e71
+Bug: https://github.com/composer/composer/security/advisories/GHSA-59pp-r3rg-353g
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2025-67746
+---
+ src/Composer/Advisory/Auditor.php        |   4 +-
+ src/Composer/IO/ConsoleIO.php            |  46 ++++++-
+ tests/Composer/Test/IO/ConsoleIOTest.php | 200 +++++++++++++++++++++++++++++++
+ 3 files changed, 243 insertions(+), 7 deletions(-)
+
+diff --git a/src/Composer/Advisory/Auditor.php b/src/Composer/Advisory/Auditor.php
+index 485b332..3759787 100644
+--- a/src/Composer/Advisory/Auditor.php
++++ b/src/Composer/Advisory/Auditor.php
+@@ -295,7 +295,7 @@ class Auditor
+                 $io->getTable()
+                     ->setHorizontal()
+                     ->setHeaders($headers)
+-                    ->addRow($row)
++                    ->addRow(ConsoleIO::sanitize($row))
+                     ->setColumnWidth(1, 80)
+                     ->setColumnMaxWidth(1, 80)
+                     ->render();
+@@ -368,7 +368,7 @@ class Auditor
+ 
+         foreach ($packages as $pkg) {
+             $replacement = $pkg->getReplacementPackage() !== null ? $pkg->getReplacementPackage() : 'none';
+-            $table->addRow([$this->getPackageNameWithLink($pkg), $replacement]);
++            $table->addRow(ConsoleIO::sanitize([$this->getPackageNameWithLink($pkg), $replacement]));
+         }
+ 
+         $table->render();
+diff --git a/src/Composer/IO/ConsoleIO.php b/src/Composer/IO/ConsoleIO.php
+index 8ecea42..9d180ca 100644
+--- a/src/Composer/IO/ConsoleIO.php
++++ b/src/Composer/IO/ConsoleIO.php
+@@ -12,6 +12,7 @@
+ 
+ namespace Composer\IO;
+ 
++use Composer\Pcre\Preg;
+ use Composer\Question\StrictConfirmationQuestion;
+ use Symfony\Component\Console\Helper\HelperSet;
+ use Symfony\Component\Console\Helper\ProgressBar;
+@@ -120,6 +121,8 @@ class ConsoleIO extends BaseIO
+      */
+     public function write($messages, bool $newline = true, int $verbosity = self::NORMAL)
+     {
++        $messages = self::sanitize($messages);
++
+         $this->doWrite($messages, $newline, false, $verbosity);
+     }
+ 
+@@ -128,6 +131,8 @@ class ConsoleIO extends BaseIO
+      */
+     public function writeError($messages, bool $newline = true, int $verbosity = self::NORMAL)
+     {
++        $messages = self::sanitize($messages);
++
+         $this->doWrite($messages, $newline, true, $verbosity);
+     }
+ 
+@@ -252,7 +257,7 @@ class ConsoleIO extends BaseIO
+     {
+         /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
+         $helper = $this->helperSet->get('question');
+-        $question = new Question($question, $default);
++        $question = new Question(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
+ 
+         return $helper->ask($this->input, $this->getErrorOutput(), $question);
+     }
+@@ -264,7 +269,7 @@ class ConsoleIO extends BaseIO
+     {
+         /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
+         $helper = $this->helperSet->get('question');
+-        $question = new StrictConfirmationQuestion($question, $default);
++        $question = new StrictConfirmationQuestion(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
+ 
+         return $helper->ask($this->input, $this->getErrorOutput(), $question);
+     }
+@@ -276,7 +281,7 @@ class ConsoleIO extends BaseIO
+     {
+         /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
+         $helper = $this->helperSet->get('question');
+-        $question = new Question($question, $default);
++        $question = new Question(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
+         $question->setValidator($validator);
+         $question->setMaxAttempts($attempts);
+ 
+@@ -290,7 +295,7 @@ class ConsoleIO extends BaseIO
+     {
+         /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
+         $helper = $this->helperSet->get('question');
+-        $question = new Question($question);
++        $question = new Question(self::sanitize($question));
+         $question->setHidden(true);
+ 
+         return $helper->ask($this->input, $this->getErrorOutput(), $question);
+@@ -303,7 +308,7 @@ class ConsoleIO extends BaseIO
+     {
+         /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
+         $helper = $this->helperSet->get('question');
+-        $question = new ChoiceQuestion($question, $choices, $default);
++        $question = new ChoiceQuestion(self::sanitize($question), self::sanitize($choices), is_string($default) ? self::sanitize($default) : $default);
+         $question->setMaxAttempts($attempts ?: null); // IOInterface requires false, and Question requires null or int
+         $question->setErrorMessage($errorMessage);
+         $question->setMultiselect($multiselect);
+@@ -342,4 +347,35 @@ class ConsoleIO extends BaseIO
+ 
+         return $this->output;
+     }
++
++    /**
++     * Sanitize string to remove control characters
++     *
++     * If $allowNewlines is true, \x0A (\n) and \x0D\x0A (\r\n) are let through. Single \r are still sanitized away to prevent overwriting whole lines.
++     *
++     * All other control chars (except NULL bytes) as well as ANSI escape sequences are removed.
++     *
++     * @param string|iterable<string> $messages
++     * @return string|array<string>
++     * @phpstan-return ($messages is string ? string : array<string>)
++     */
++    public static function sanitize($messages, bool $allowNewlines = true)
++    {
++        // Match ANSI escape sequences:
++        // - CSI (Control Sequence Introducer): ESC [ params intermediate final
++        // - OSC (Operating System Command): ESC ] ... ESC \ or BEL
++        // - Other ESC sequences: ESC followed by any character
++        $escapePattern = '\x1B\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]|\x1B\].*?(?:\x1B\\\\|\x07)|\x1B.';
++        $pattern = $allowNewlines ? "{{$escapePattern}|[\x01-\x09\x0B\x0C\x0E-\x1A]|\r(?!\n)}u" : "{{$escapePattern}|[\x01-\x1A]}u";
++        if (is_string($messages)) {
++            return Preg::replace($pattern, '', $messages);
++        }
++
++        $sanitized = [];
++        foreach ($messages as $key => $message) {
++            $sanitized[$key] = Preg::replace($pattern, '', $message);
++        }
++
++        return $sanitized;
++    }
+ }
+diff --git a/tests/Composer/Test/IO/ConsoleIOTest.php b/tests/Composer/Test/IO/ConsoleIOTest.php
+index 8e0a829..cf38bf4 100644
+--- a/tests/Composer/Test/IO/ConsoleIOTest.php
++++ b/tests/Composer/Test/IO/ConsoleIOTest.php
+@@ -296,4 +296,204 @@ class ConsoleIOTest extends TestCase
+         self::assertTrue($consoleIO->hasAuthentication('repoName'));
+         self::assertFalse($consoleIO->hasAuthentication('repoName2'));
+     }
++
++    /**
++     * @dataProvider sanitizeProvider
++     * @param string|string[] $input
++     * @param string|string[] $expected
++     */
++    public function testSanitize($input, bool $allowNewlines, $expected): void
++    {
++        self::assertSame($expected, ConsoleIO::sanitize($input, $allowNewlines));
++    }
++
++    /**
++     * @return array<string, array{input: string|string[], allowNewlines: bool, expected: string|string[]}>
++     */
++    public static function sanitizeProvider(): array
++    {
++        return [
++            // String input with allowNewlines=true
++            'string with \n allowed' => [
++                'input' => "Hello\nWorld",
++                'allowNewlines' => true,
++                'expected' => "Hello\nWorld",
++            ],
++            'string with \r\n allowed' => [
++                'input' => "Hello\r\nWorld",
++                'allowNewlines' => true,
++                'expected' => "Hello\r\nWorld",
++            ],
++            'string with standalone \r removed' => [
++                'input' => "Hello\rWorld",
++                'allowNewlines' => true,
++                'expected' => "HelloWorld",
++            ],
++            'string with escape sequence removed' => [
++                'input' => "Hello\x1B[31mWorld",
++                'allowNewlines' => true,
++                'expected' => "HelloWorld",
++            ],
++            'string with control chars removed' => [
++                'input' => "Hello\x01\x08\x09World",
++                'allowNewlines' => true,
++                'expected' => "HelloWorld",
++            ],
++            'string with mixed control chars and newlines' => [
++                'input' => "Line1\n\x1B[32mLine2\x08\rLine3",
++                'allowNewlines' => true,
++                'expected' => "Line1\nLine2Line3",
++            ],
++            'string with null bytes are allowed' => [
++                'input' => "Hello\x00World",
++                'allowNewlines' => true,
++                'expected' => "Hello\x00World",
++            ],
++
++            // String input with allowNewlines=false
++            'string with \n removed' => [
++                'input' => "Hello\nWorld",
++                'allowNewlines' => false,
++                'expected' => "HelloWorld",
++            ],
++            'string with \r\n removed' => [
++                'input' => "Hello\r\nWorld",
++                'allowNewlines' => false,
++                'expected' => "HelloWorld",
++            ],
++            'string with escape sequence removed (no newlines)' => [
++                'input' => "Hello\x1B[31mWorld",
++                'allowNewlines' => false,
++                'expected' => "HelloWorld",
++            ],
++            'string with all control chars removed' => [
++                'input' => "Hello\x01\x08\x09\x0A\x0DWorld",
++                'allowNewlines' => false,
++                'expected' => "HelloWorld",
++            ],
++
++            // Array input with allowNewlines=true
++            'array with newlines allowed' => [
++                'input' => ["Hello\nWorld", "Foo\r\nBar"],
++                'allowNewlines' => true,
++                'expected' => ["Hello\nWorld", "Foo\r\nBar"],
++            ],
++            'array with control chars removed' => [
++                'input' => ["Hello\x1B[31mWorld", "Foo\x08Bar\r"],
++                'allowNewlines' => true,
++                'expected' => ["HelloWorld", "FooBar"],
++            ],
++
++            // Array input with allowNewlines=false
++            'array with newlines removed' => [
++                'input' => ["Hello\nWorld", "Foo\r\nBar"],
++                'allowNewlines' => false,
++                'expected' => ["HelloWorld", "FooBar"],
++            ],
++            'array with all control chars removed' => [
++                'input' => ["Test\x01\x0A", "Data\x1B[m\x0D"],
++                'allowNewlines' => false,
++                'expected' => ["Test", "Data"],
++            ],
++
++            // Edge cases
++            'empty string' => [
++                'input' => '',
++                'allowNewlines' => true,
++                'expected' => '',
++            ],
++            'empty array' => [
++                'input' => [],
++                'allowNewlines' => true,
++                'expected' => [],
++            ],
++            'string with no control chars' => [
++                'input' => 'Hello World',
++                'allowNewlines' => true,
++                'expected' => 'Hello World',
++            ],
++            'string with unicode' => [
++                'input' => "Hello 世界\nTest",
++                'allowNewlines' => true,
++                'expected' => "Hello 世界\nTest",
++            ],
++
++            // Various ANSI escape sequences
++            'CSI with multiple parameters' => [
++                'input' => "Text\x1B[1;31;40mColored\x1B[0mNormal",
++                'allowNewlines' => true,
++                'expected' => "TextColoredNormal",
++            ],
++            'CSI SGR reset' => [
++                'input' => "Before\x1B[mAfter",
++                'allowNewlines' => true,
++                'expected' => "BeforeAfter",
++            ],
++            'CSI cursor positioning' => [
++                'input' => "Line\x1B[2J\x1B[H\x1B[10;5HText",
++                'allowNewlines' => true,
++                'expected' => "LineText",
++            ],
++            'OSC with BEL terminator' => [
++                'input' => "Text\x1B]0;Window Title\x07More",
++                'allowNewlines' => true,
++                'expected' => "TextMore",
++            ],
++            'OSC with ST terminator' => [
++                'input' => "Text\x1B]2;Title\x1B\\More",
++                'allowNewlines' => true,
++                'expected' => "TextMore",
++            ],
++            'Simple ESC sequences' => [
++                'input' => "Text\x1B7Saved\x1B8Restored\x1BcReset",
++                'allowNewlines' => true,
++                'expected' => "TextSavedRestoredReset",
++            ],
++            'ESC D (Index)' => [
++                'input' => "Line1\x1BDLine2",
++                'allowNewlines' => true,
++                'expected' => "Line1Line2",
++            ],
++            'ESC E (Next Line)' => [
++                'input' => "Line1\x1BELine2",
++                'allowNewlines' => true,
++                'expected' => "Line1Line2",
++            ],
++            'ESC M (Reverse Index)' => [
++                'input' => "Text\x1BMMore",
++                'allowNewlines' => true,
++                'expected' => "TextMore",
++            ],
++            'ESC N (SS2) and ESC O (SS3)' => [
++                'input' => "Text\x1BNchar\x1BOanother",
++                'allowNewlines' => true,
++                'expected' => "Textcharanother",
++            ],
++            'Multiple escape sequences in sequence' => [
++                'input' => "\x1B[1m\x1B[31m\x1B[44mBold Red on Blue\x1B[0m",
++                'allowNewlines' => true,
++                'expected' => "Bold Red on Blue",
++            ],
++            'CSI with question mark (private mode)' => [
++                'input' => "Text\x1B[?25lHidden\x1B[?25hVisible",
++                'allowNewlines' => true,
++                'expected' => "TextHiddenVisible",
++            ],
++            'CSI erase sequences' => [
++                'input' => "Clear\x1B[2J\x1B[K\x1B[1KScreen",
++                'allowNewlines' => true,
++                'expected' => "ClearScreen",
++            ],
++            'Hyperlink OSC 8' => [
++                'input' => "Click \x1B]8;;https://example.com\x1B\\here\x1B]8;;\x1B\\ for link",
++                'allowNewlines' => true,
++                'expected' => "Click here for link",
++            ],
++            'Mixed content with complex sequences' => [
++                'input' => "\x1B[1;33mWarning:\x1B[0m File\x1B[31m not\x1B[0m found\n\x1B[2KRetrying...",
++                'allowNewlines' => true,
++                'expected' => "Warning: File not found\nRetrying...",
++            ],
++        ];
++    }
+ }
diff -Nru composer-2.8.8/debian/patches/series composer-2.8.8/debian/patches/series
--- composer-2.8.8/debian/patches/series	2025-04-05 11:50:09.000000000 +0200
+++ composer-2.8.8/debian/patches/series	2025-12-30 16:33:32.000000000 +0100
@@ -14,3 +14,4 @@
 0014-Revert-Add-workaround-for-InstalledVersion-to-ensure.patch
 0015-Revert-Fix-regression-from-12233-in-InstalledVersion.patch
 0016-Modernize-PHPUnit-syntax.patch
+0017-Merge-commit-from-fork.patch

Attachment: signature.asc
Description: PGP signature


--- End Message ---
--- Begin Message ---
Package: release.debian.org\nVersion: 13.3\n\nThis update has been released as 
part of Debian 13.3.

--- End Message ---

Reply via email to