Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected] Control: affects -1 + src:php-league-commonmark User: [email protected] Usertags: pu
Hi, As agreed with the security team, I’d like to address the following two security issues via the next point release (as in #1132184 for bookworm). * Fix DisallowedRawHtml bypass via newline/tab in tag names [CVE-2026-30838] * Fix DomainFilteringAdapter hostname boundary bypass [CVE-2026-33347] [ 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 php-league-commonmark-2.7.0/debian/changelog php-league-commonmark-2.7.0/debian/changelog --- php-league-commonmark-2.7.0/debian/changelog 2025-05-05 16:16:52.000000000 +0200 +++ php-league-commonmark-2.7.0/debian/changelog 2026-03-26 07:55:35.000000000 +0100 @@ -1,7 +1,16 @@ +php-league-commonmark (2.7.0-1+deb13u1) trixie; urgency=medium + + * Track debian/trixie + * Fix DisallowedRawHtml bypass via newline/tab in tag names [CVE-2026-30838] + * Fix DomainFilteringAdapter hostname boundary bypass [CVE-2026-33347] + * Document CVE fixed in previous changelog entry + + -- David Prévot <[email protected]> Thu, 26 Mar 2026 07:55:35 +0100 + php-league-commonmark (2.7.0-1) unstable; urgency=medium [ Colin O'Dell ] - * Fix XSS in AttributesExtension + * Fix XSS in AttributesExtension [CVE-2025-46734] * Prepare to release 2.7.0 -- David Prévot <[email protected]> Mon, 05 May 2025 16:16:52 +0200 diff -Nru php-league-commonmark-2.7.0/debian/control php-league-commonmark-2.7.0/debian/control --- php-league-commonmark-2.7.0/debian/control 2025-05-05 16:07:46.000000000 +0200 +++ php-league-commonmark-2.7.0/debian/control 2026-03-26 07:55:35.000000000 +0100 @@ -17,7 +17,7 @@ phpunit Standards-Version: 4.7.2 Homepage: https://commonmark.thephpleague.com/ -Vcs-Git: https://salsa.debian.org/php-team/pear/php-league-commonmark.git -b debian/latest +Vcs-Git: https://salsa.debian.org/php-team/pear/php-league-commonmark.git -b debian/trixie Vcs-Browser: https://salsa.debian.org/php-team/pear/php-league-commonmark Rules-Requires-Root: no diff -Nru php-league-commonmark-2.7.0/debian/gbp.conf php-league-commonmark-2.7.0/debian/gbp.conf --- php-league-commonmark-2.7.0/debian/gbp.conf 2024-07-23 12:20:01.000000000 +0200 +++ php-league-commonmark-2.7.0/debian/gbp.conf 2026-03-26 07:55:35.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 php-league-commonmark-2.7.0/debian/patches/0005-Add-regression-test.patch php-league-commonmark-2.7.0/debian/patches/0005-Add-regression-test.patch --- php-league-commonmark-2.7.0/debian/patches/0005-Add-regression-test.patch 1970-01-01 01:00:00.000000000 +0100 +++ php-league-commonmark-2.7.0/debian/patches/0005-Add-regression-test.patch 2026-03-26 07:55:35.000000000 +0100 @@ -0,0 +1,42 @@ +From: Colin O'Dell <[email protected]> +Date: Thu, 5 Mar 2026 07:22:58 -0500 +Subject: Add regression test + +Origin: upstream, https://github.com/thephpleague/commonmark/commit/f6e74434dd1a91f195f80cb0184b746a4187272a +--- + .../DisallowedRawHtml/DisallowedRawHtmlRendererTest.php | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php +index 66c4bad..d64d699 100644 +--- a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php ++++ b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php +@@ -70,6 +70,16 @@ final class DisallowedRawHtmlRendererTest extends TestCase + yield ['<script>', '<script>']; + yield ['<plaintext>', '<plaintext>']; + ++ // Newline/whitespace bypass attempts (security fix) ++ yield ["<script >", "<script >"]; ++ yield ["<script\n>", "<script\n>"]; ++ yield ["<script\t>", "<script\t>"]; ++ yield ["<script\r\n>", "<script\r\n>"]; ++ yield ["<iframe\nwidth=\"560\">", "<iframe\nwidth=\"560\">"]; ++ ++ // Ensure non-disallowed tags with similar names are NOT filtered ++ yield ['<scriptfoo>', '<scriptfoo>']; ++ + // Tags not escaped by default + yield ['<strong>', '<strong>']; + } +@@ -104,6 +114,11 @@ final class DisallowedRawHtmlRendererTest extends TestCase + yield ['<strong/>', '<strong/>']; + yield ['<strong />', '<strong />']; + ++ // Newline bypass with custom config ++ yield ["<strong >", "<strong >"]; ++ yield ["<strong\n>", "<strong\n>"]; ++ yield ["<strong\t>", "<strong\t>"]; ++ + // Defaults that I didn't include in my custom config + yield ['<title>', '<title>']; + yield ['<textarea>', '<textarea>']; diff -Nru php-league-commonmark-2.7.0/debian/patches/0006-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch php-league-commonmark-2.7.0/debian/patches/0006-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch --- php-league-commonmark-2.7.0/debian/patches/0006-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch 1970-01-01 01:00:00.000000000 +0100 +++ php-league-commonmark-2.7.0/debian/patches/0006-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch 2026-03-26 07:55:35.000000000 +0100 @@ -0,0 +1,47 @@ +From: Colin O'Dell <[email protected]> +Date: Thu, 5 Mar 2026 07:43:00 -0500 +Subject: Fix DisallowedRawHtml bypass via newline/tab in tag names + +Origin: upstream, https://github.com/thephpleague/commonmark/commit/5c0c4c8fe5a31e8260be99e0afad7136a27c79e6 +Bug: https://github.com/thephpleague/commonmark/security/advisories/GHSA-4v6x-c7xx-hw9f +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-30838 +--- + src/Extension/DisallowedRawHtml/DisallowedRawHtmlRenderer.php | 2 +- + .../Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlRenderer.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlRenderer.php +index 06252a3..2bcb89a 100644 +--- a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlRenderer.php ++++ b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlRenderer.php +@@ -45,7 +45,7 @@ final class DisallowedRawHtmlRenderer implements NodeRendererInterface, Configur + return $rendered; + } + +- $regex = \sprintf('/<(\/?(?:%s)[ \/>])/i', \implode('|', \array_map('preg_quote', $tags))); ++ $regex = \sprintf('/<(\/?(?:%s)[\s\/>])/i', \implode('|', \array_map('preg_quote', $tags))); + + // Match these types of tags: <title> </title> <title x="sdf"> <title/> <title /> + return \preg_replace($regex, '<$1', $rendered); +diff --git a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php +index d64d699..36d4c18 100644 +--- a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php ++++ b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php +@@ -71,7 +71,7 @@ final class DisallowedRawHtmlRendererTest extends TestCase + yield ['<plaintext>', '<plaintext>']; + + // Newline/whitespace bypass attempts (security fix) +- yield ["<script >", "<script >"]; ++ yield ['<script >', '<script >']; + yield ["<script\n>", "<script\n>"]; + yield ["<script\t>", "<script\t>"]; + yield ["<script\r\n>", "<script\r\n>"]; +@@ -115,7 +115,7 @@ final class DisallowedRawHtmlRendererTest extends TestCase + yield ['<strong />', '<strong />']; + + // Newline bypass with custom config +- yield ["<strong >", "<strong >"]; ++ yield ['<strong >', '<strong >']; + yield ["<strong\n>", "<strong\n>"]; + yield ["<strong\t>", "<strong\t>"]; + diff -Nru php-league-commonmark-2.7.0/debian/patches/0007-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch php-league-commonmark-2.7.0/debian/patches/0007-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch --- php-league-commonmark-2.7.0/debian/patches/0007-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch 1970-01-01 01:00:00.000000000 +0100 +++ php-league-commonmark-2.7.0/debian/patches/0007-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch 2026-03-26 07:55:35.000000000 +0100 @@ -0,0 +1,109 @@ +From: Colin O'Dell <[email protected]> +Date: Thu, 19 Mar 2026 09:01:30 -0400 +Subject: Fix DomainFilteringAdapter hostname boundary bypass + +Origin: backport, https://github.com/thephpleague/commonmark/commit/59fb075d2101740c337c7216e3f32b36c204218b +Bug: https://github.com/thephpleague/commonmark/security/advisories/GHSA-hh8v-hgvp-g3f5 +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-33347 +--- + src/Extension/Embed/DomainFilteringAdapter.php | 41 +++++++++++++--------- + .../Extension/Embed/DomainFilteringAdapterTest.php | 18 ++++++++-- + 2 files changed, 41 insertions(+), 18 deletions(-) + +diff --git a/src/Extension/Embed/DomainFilteringAdapter.php b/src/Extension/Embed/DomainFilteringAdapter.php +index d150764..b00b028 100644 +--- a/src/Extension/Embed/DomainFilteringAdapter.php ++++ b/src/Extension/Embed/DomainFilteringAdapter.php +@@ -17,16 +17,16 @@ class DomainFilteringAdapter implements EmbedAdapterInterface + { + private EmbedAdapterInterface $decorated; + +- /** @psalm-var non-empty-string */ +- private string $regex; ++ /** @var string[] */ ++ private array $allowedDomains; + + /** + * @param string[] $allowedDomains + */ + public function __construct(EmbedAdapterInterface $decorated, array $allowedDomains) + { +- $this->decorated = $decorated; +- $this->regex = self::createRegex($allowedDomains); ++ $this->decorated = $decorated; ++ $this->allowedDomains = \array_map('strtolower', $allowedDomains); + } + + /** +@@ -34,20 +34,29 @@ class DomainFilteringAdapter implements EmbedAdapterInterface + */ + public function updateEmbeds(array $embeds): void + { +- $this->decorated->updateEmbeds(\array_values(\array_filter($embeds, function (Embed $embed): bool { +- return \preg_match($this->regex, $embed->getUrl()) === 1; +- }))); ++ $this->decorated->updateEmbeds(\array_values(\array_filter($embeds, [$this, 'isAllowed']))); + } + +- /** +- * @param string[] $allowedDomains +- * +- * @psalm-return non-empty-string +- */ +- private static function createRegex(array $allowedDomains): string ++ private function isAllowed(Embed $embed): bool + { +- $allowedDomains = \array_map('preg_quote', $allowedDomains); +- +- return '/^(?:https?:\/\/)?(?:[^.]+\.)*(' . \implode('|', $allowedDomains) . ')/'; ++ $url = $embed->getUrl(); ++ $scheme = \parse_url($url, \PHP_URL_SCHEME); ++ if ($scheme === null || $scheme === false) { ++ // Bare domain (no scheme) - assume https:// so parse_url can extract the host ++ $url = 'https://' . $url; ++ } elseif (\strtolower($scheme) !== 'http' && \strtolower($scheme) !== 'https') { ++ return false; ++ } ++ ++ $host = \parse_url($url, \PHP_URL_HOST); ++ $host = \strtolower(\rtrim((string) $host, '.')); ++ ++ foreach ($this->allowedDomains as $domain) { ++ if ($host === $domain || \str_ends_with($host, '.' . $domain)) { ++ return true; ++ } ++ } ++ ++ return false; + } + } +diff --git a/tests/unit/Extension/Embed/DomainFilteringAdapterTest.php b/tests/unit/Extension/Embed/DomainFilteringAdapterTest.php +index 436e398..d320eb7 100644 +--- a/tests/unit/Extension/Embed/DomainFilteringAdapterTest.php ++++ b/tests/unit/Extension/Embed/DomainFilteringAdapterTest.php +@@ -28,9 +28,23 @@ final class DomainFilteringAdapterTest extends TestCase + $embed2 = new Embed('foo.example.com'), + new Embed('www.bar.com'), + new Embed('badexample.com'), +- $embed3 = new Embed('http://foo.bar.com'), +- $embed4 = new Embed('https://foo.bar.com/baz'), ++ $embed3 = new Embed('HTTP://foo.bar.com'), ++ $embed4 = new Embed('hTtPs://foo.bar.com/baz'), + new Embed('https://bar.com'), ++ new Embed('https://example.com.evil'), ++ new Embed('https://example.com.evil/path'), ++ new Embed('https://foo.bar.com.evil'), ++ new Embed('example.com.evil'), ++ new Embed('example.com.evil/path'), ++ new Embed('foo.bar.com.evil'), ++ new Embed('https://[email protected]'), ++ new Embed('https://user:[email protected]'), ++ new Embed('https://example.com:[email protected]/path'), ++ new Embed('javascript:alert(1)'), ++ new Embed('ftp://example.com'), ++ new Embed('file:///etc/passwd'), ++ new Embed('data:text/html,<script>alert(1)</script>'), ++ new Embed('//example.com/path'), + ]; + + $inner = $this->createMock(EmbedAdapterInterface::class); diff -Nru php-league-commonmark-2.7.0/debian/patches/series php-league-commonmark-2.7.0/debian/patches/series --- php-league-commonmark-2.7.0/debian/patches/series 2025-05-05 16:07:48.000000000 +0200 +++ php-league-commonmark-2.7.0/debian/patches/series 2026-03-26 07:55:35.000000000 +0100 @@ -2,3 +2,6 @@ 0002-Drop-tests-breaking-under-PHPUnit-11.patch 0003-Mark-Data-Provider-method-as-static.patch 0004-Modernize-PHPUnit-syntax.patch +0005-Add-regression-test.patch +0006-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch +0007-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch
signature.asc
Description: PGP signature

