--- Begin Message ---
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
--- End Message ---