Your message dated Sat, 16 May 2026 11:07:43 +0000
with message-id <[email protected]>
and subject line Released with 12.14
has caused the Debian Bug report #1132184,
regarding bookworm-pu: package php-league-commonmark/2.3.9-1+deb12u1
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.)


-- 
1132184: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1132184
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
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
three security issues via the next point release.

  * Fix XSS in AttributesExtension [CVE-2025-46734]
  * 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.3.9/debian/changelog php-league-commonmark-2.3.9/debian/changelog
--- php-league-commonmark-2.3.9/debian/changelog	2023-02-15 18:38:28.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/changelog	2026-03-26 08:15:50.000000000 +0100
@@ -1,3 +1,12 @@
+php-league-commonmark (2.3.9-1+deb12u1) bookworm; urgency=medium
+
+  * Track Bookworm branch
+  * Fix XSS in AttributesExtension [CVE-2025-46734]
+  * Fix DisallowedRawHtml bypass via newline/tab in tag names [CVE-2026-30838]
+  * Fix DomainFilteringAdapter hostname boundary bypass [CVE-2026-33347]
+
+ -- David Prévot <[email protected]>  Thu, 26 Mar 2026 08:15:50 +0100
+
 php-league-commonmark (2.3.9-1) unstable; urgency=medium
 
   [ Colin O'Dell ]
diff -Nru php-league-commonmark-2.3.9/debian/control php-league-commonmark-2.3.9/debian/control
--- php-league-commonmark-2.3.9/debian/control	2023-02-15 18:36:22.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/control	2026-03-26 08:15:50.000000000 +0100
@@ -18,7 +18,7 @@
                pkg-php-tools (>= 1.41~)
 Standards-Version: 4.6.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/bookworm-security
 Vcs-Browser: https://salsa.debian.org/php-team/pear/php-league-commonmark
 Rules-Requires-Root: no
 
diff -Nru php-league-commonmark-2.3.9/debian/gbp.conf php-league-commonmark-2.3.9/debian/gbp.conf
--- php-league-commonmark-2.3.9/debian/gbp.conf	2022-01-25 19:18:49.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/gbp.conf	2026-03-26 08:15:50.000000000 +0100
@@ -1,5 +1,5 @@
 [DEFAULT]
-debian-branch = debian/latest
+debian-branch = debian/bookworm-security
 filter = [ '.gitattributes' ]
 pristine-tar = True
 upstream-vcs-tag = %(version%~%-)s
diff -Nru php-league-commonmark-2.3.9/debian/patches/0002-Fix-XSS-in-AttributesExtension.patch php-league-commonmark-2.3.9/debian/patches/0002-Fix-XSS-in-AttributesExtension.patch
--- php-league-commonmark-2.3.9/debian/patches/0002-Fix-XSS-in-AttributesExtension.patch	1970-01-01 01:00:00.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/patches/0002-Fix-XSS-in-AttributesExtension.patch	2026-03-26 08:15:50.000000000 +0100
@@ -0,0 +1,296 @@
+From: Colin O'Dell <[email protected]>
+Date: Mon, 5 May 2025 07:53:56 -0400
+Subject: Fix XSS in AttributesExtension
+
+Origin: backport, https://github.com/thephpleague/commonmark/commit/43207253ea5f14867c77c697cd3838c446cadcea
+Bug: https://github.com/thephpleague/commonmark/security/advisories/GHSA-3527-qv2q-pfvx
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2025-46734
+---
+ src/Extension/Attributes/AttributesExtension.php   | 18 +++++-
+ .../Attributes/Event/AttributesListener.php        | 15 ++++-
+ src/Extension/Attributes/Util/AttributesHelper.php | 38 +++++++++++++
+ .../Extension/Attributes/data/allowlist.html       |  3 +
+ .../Extension/Attributes/data/allowlist.md         | 12 ++++
+ .../Attributes/data/js_event_attributes.html       |  1 +
+ .../Attributes/data/js_event_attributes.md         |  1 +
+ .../Attributes/data/unsafe_links_allowed.html      |  1 +
+ .../Attributes/data/unsafe_links_allowed.md        |  5 ++
+ .../Attributes/data/unsafe_links_blocked.html      |  1 +
+ .../Attributes/data/unsafe_links_blocked.md        |  5 ++
+ .../Attributes/Util/AttributesHelperTest.php       | 66 ++++++++++++++++++++++
+ 12 files changed, 162 insertions(+), 4 deletions(-)
+ create mode 100644 tests/functional/Extension/Attributes/data/allowlist.html
+ create mode 100644 tests/functional/Extension/Attributes/data/allowlist.md
+ create mode 100644 tests/functional/Extension/Attributes/data/js_event_attributes.html
+ create mode 100644 tests/functional/Extension/Attributes/data/js_event_attributes.md
+ create mode 100644 tests/functional/Extension/Attributes/data/unsafe_links_allowed.html
+ create mode 100644 tests/functional/Extension/Attributes/data/unsafe_links_allowed.md
+ create mode 100644 tests/functional/Extension/Attributes/data/unsafe_links_blocked.html
+ create mode 100644 tests/functional/Extension/Attributes/data/unsafe_links_blocked.md
+
+diff --git a/src/Extension/Attributes/AttributesExtension.php b/src/Extension/Attributes/AttributesExtension.php
+index 2ef3d85..b29606d 100644
+--- a/src/Extension/Attributes/AttributesExtension.php
++++ b/src/Extension/Attributes/AttributesExtension.php
+@@ -19,14 +19,26 @@ use League\CommonMark\Event\DocumentParsedEvent;
+ use League\CommonMark\Extension\Attributes\Event\AttributesListener;
+ use League\CommonMark\Extension\Attributes\Parser\AttributesBlockStartParser;
+ use League\CommonMark\Extension\Attributes\Parser\AttributesInlineParser;
+-use League\CommonMark\Extension\ExtensionInterface;
++use League\CommonMark\Extension\ConfigurableExtensionInterface;
++use League\Config\ConfigurationBuilderInterface;
++use Nette\Schema\Expect;
+ 
+-final class AttributesExtension implements ExtensionInterface
++final class AttributesExtension implements ConfigurableExtensionInterface
+ {
++    public function configureSchema(ConfigurationBuilderInterface $builder): void
++    {
++        $builder->addSchema('attributes', Expect::structure([
++            'allow' => Expect::arrayOf('string')->default([]),
++        ]));
++    }
++
+     public function register(EnvironmentBuilderInterface $environment): void
+     {
++        $allowList        = $environment->getConfiguration()->get('attributes.allow');
++        $allowUnsafeLinks = $environment->getConfiguration()->get('allow_unsafe_links');
++
+         $environment->addBlockStartParser(new AttributesBlockStartParser());
+         $environment->addInlineParser(new AttributesInlineParser());
+-        $environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener(), 'processDocument']);
++        $environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener($allowList, $allowUnsafeLinks), 'processDocument']);
+     }
+ }
+diff --git a/src/Extension/Attributes/Event/AttributesListener.php b/src/Extension/Attributes/Event/AttributesListener.php
+index feec8cc..fa068f4 100644
+--- a/src/Extension/Attributes/Event/AttributesListener.php
++++ b/src/Extension/Attributes/Event/AttributesListener.php
+@@ -29,6 +29,19 @@ final class AttributesListener
+     private const DIRECTION_PREFIX = 'prefix';
+     private const DIRECTION_SUFFIX = 'suffix';
+ 
++    /** @var list<string> */
++    private array $allowList;
++    private bool $allowUnsafeLinks;
++
++    /**
++     * @param list<string> $allowList
++     */
++    public function __construct(array $allowList = [], bool $allowUnsafeLinks = true)
++    {
++        $this->allowList        = $allowList;
++        $this->allowUnsafeLinks = $allowUnsafeLinks;
++    }
++
+     public function processDocument(DocumentParsedEvent $event): void
+     {
+         foreach ($event->getDocument()->iterator() as $node) {
+@@ -50,7 +63,7 @@ final class AttributesListener
+                     $attributes = AttributesHelper::mergeAttributes($node->getAttributes(), $target);
+                 }
+ 
+-                $target->data->set('attributes', $attributes);
++                $target->data->set('attributes', AttributesHelper::filterAttributes($attributes, $this->allowList, $this->allowUnsafeLinks));
+             }
+ 
+             $node->detach();
+diff --git a/src/Extension/Attributes/Util/AttributesHelper.php b/src/Extension/Attributes/Util/AttributesHelper.php
+index de5c111..33d3a0a 100644
+--- a/src/Extension/Attributes/Util/AttributesHelper.php
++++ b/src/Extension/Attributes/Util/AttributesHelper.php
+@@ -134,4 +134,42 @@ final class AttributesHelper
+ 
+         return $attributes;
+     }
++
++    /**
++     * @param array<string, mixed> $attributes
++     * @param list<string>         $allowList
++     *
++     * @return array<string, mixed>
++     */
++    public static function filterAttributes(array $attributes, array $allowList, bool $allowUnsafeLinks): array
++    {
++        $allowList = \array_fill_keys($allowList, true);
++
++        foreach ($attributes as $name => $value) {
++            $attrNameLower = \strtolower($name);
++
++            // Remove any unsafe links
++            if (! $allowUnsafeLinks && ($attrNameLower === 'href' || $attrNameLower === 'src') && \is_string($value) && RegexHelper::isLinkPotentiallyUnsafe($value)) {
++                unset($attributes[$name]);
++                continue;
++            }
++
++            // No allowlist?
++            if ($allowList === []) {
++                // Just remove JS event handlers
++                if (\str_starts_with($attrNameLower, 'on')) {
++                    unset($attributes[$name]);
++                }
++
++                continue;
++            }
++
++            // Remove any attributes not in that allowlist (case-sensitive)
++            if (! isset($allowList[$name])) {
++                unset($attributes[$name]);
++            }
++        }
++
++        return $attributes;
++    }
+ }
+diff --git a/tests/functional/Extension/Attributes/data/allowlist.html b/tests/functional/Extension/Attributes/data/allowlist.html
+new file mode 100644
+index 0000000..92ab9de
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/allowlist.html
+@@ -0,0 +1,3 @@
++<h2 id="header1">Header with attributes</h2>
++<p class="text">some text</p>
++<p><img align="left" src="/assets/image.jpg" alt="image" /></p>
+diff --git a/tests/functional/Extension/Attributes/data/allowlist.md b/tests/functional/Extension/Attributes/data/allowlist.md
+new file mode 100644
+index 0000000..996c647
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/allowlist.md
+@@ -0,0 +1,12 @@
++---
++attributes:
++    allow: [id, class, align]
++---
++
++Header with attributes {#header1}
++---------------------------------
++
++{class="text" hello="world"}
++some text
++
++![image](/assets/image.jpg){align=left width=100px}
+diff --git a/tests/functional/Extension/Attributes/data/js_event_attributes.html b/tests/functional/Extension/Attributes/data/js_event_attributes.html
+new file mode 100644
+index 0000000..667c05e
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/js_event_attributes.html
+@@ -0,0 +1 @@
++<p><img class="blocked" src="" alt="this extension blocks js event attributes" /></p>
+diff --git a/tests/functional/Extension/Attributes/data/js_event_attributes.md b/tests/functional/Extension/Attributes/data/js_event_attributes.md
+new file mode 100644
+index 0000000..e0a0642
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/js_event_attributes.md
+@@ -0,0 +1 @@
++![this extension blocks js event attributes](){onerror=alert(1) class=blocked}
+diff --git a/tests/functional/Extension/Attributes/data/unsafe_links_allowed.html b/tests/functional/Extension/Attributes/data/unsafe_links_allowed.html
+new file mode 100644
+index 0000000..3497e89
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/unsafe_links_allowed.html
+@@ -0,0 +1 @@
++<p><a href="javascript:alert(1)">click me</a></p>
+diff --git a/tests/functional/Extension/Attributes/data/unsafe_links_allowed.md b/tests/functional/Extension/Attributes/data/unsafe_links_allowed.md
+new file mode 100644
+index 0000000..9a1d45e
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/unsafe_links_allowed.md
+@@ -0,0 +1,5 @@
++---
++allow_unsafe_links: true
++---
++
++[click me](javascript:alert(1)){href="javascript:alert(1)"}
+diff --git a/tests/functional/Extension/Attributes/data/unsafe_links_blocked.html b/tests/functional/Extension/Attributes/data/unsafe_links_blocked.html
+new file mode 100644
+index 0000000..0205a6b
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/unsafe_links_blocked.html
+@@ -0,0 +1 @@
++<p><a>click me</a></p>
+diff --git a/tests/functional/Extension/Attributes/data/unsafe_links_blocked.md b/tests/functional/Extension/Attributes/data/unsafe_links_blocked.md
+new file mode 100644
+index 0000000..5c706a3
+--- /dev/null
++++ b/tests/functional/Extension/Attributes/data/unsafe_links_blocked.md
+@@ -0,0 +1,5 @@
++---
++allow_unsafe_links: false
++---
++
++[click me](javascript:alert(1)){href="javascript:alert(1)"}
+diff --git a/tests/unit/Extension/Attributes/Util/AttributesHelperTest.php b/tests/unit/Extension/Attributes/Util/AttributesHelperTest.php
+index 17a4653..67767c5 100644
+--- a/tests/unit/Extension/Attributes/Util/AttributesHelperTest.php
++++ b/tests/unit/Extension/Attributes/Util/AttributesHelperTest.php
+@@ -182,4 +182,70 @@ final class AttributesHelperTest extends TestCase
+             ['id' => 'block', 'class' => 'inline block'],
+         ];
+     }
++
++    /**
++     * @dataProvider dataForTestFilterAttributes
++     *
++     * @param array<string, mixed> $attributes
++     * @param list<string>         $allowList
++     * @param array<string, mixed> $expected
++     */
++    public function testFilterAttributes(array $attributes, array $allowList, bool $allowUnsafeLinks, array $expected): void
++    {
++        $this->assertEquals($expected, AttributesHelper::filterAttributes($attributes, $allowList, $allowUnsafeLinks));
++    }
++
++    /**
++     * @return iterable<array<mixed>>
++     */
++    public static function dataForTestFilterAttributes(): iterable
++    {
++        // No allow list; unsafe links disallowed (default behavior)
++        yield [
++            ['id' => 'foo', 'class' => 'bar', 'onclick' => 'alert("XSS")', 'href' => 'javascript:alert("XSS")'],
++            [],
++            false,
++            ['id' => 'foo', 'class' => 'bar'],
++        ];
++
++        // No allow list; unsafe links allowed
++        yield [
++            ['id' => 'foo', 'class' => 'bar', 'onclick' => 'alert("XSS")', 'href' => 'javascript:alert("XSS")'],
++            [],
++            true,
++            ['id' => 'foo', 'class' => 'bar', 'href' => 'javascript:alert("XSS")'],
++        ];
++
++        // Allow list; unsafe links disallowed
++        yield [
++            ['id' => 'foo', 'class' => 'bar', 'onclick' => 'alert("XSS")', 'href' => 'javascript:alert("XSS")'],
++            ['id', 'onclick', 'href'],
++            false,
++            ['id' => 'foo', 'onclick' => 'alert("XSS")'],
++        ];
++
++        // Allow list; unsafe links allowed
++        yield [
++            ['id' => 'foo', 'class' => 'bar', 'onclick' => 'alert("XSS")', 'href' => 'javascript:alert("XSS")'],
++            ['id', 'onclick', 'href'],
++            true,
++            ['id' => 'foo', 'onclick' => 'alert("XSS")', 'href' => 'javascript:alert("XSS")'],
++        ];
++
++        // Allow list blocks all
++        yield [
++            ['id' => 'foo', 'class' => '<script>alert("XSS")</script>'],
++            ['style'],
++            false,
++            [],
++        ];
++
++        // Can't use weird casing to bypass allowlist or 'on*' restriction
++        yield [
++            ['ID' => 'foo', 'oNcLiCk' => 'alert("XSS")'],
++            ['id', 'class'],
++            false,
++            [],
++        ];
++    }
+ }
diff -Nru php-league-commonmark-2.3.9/debian/patches/0003-Add-regression-test.patch php-league-commonmark-2.3.9/debian/patches/0003-Add-regression-test.patch
--- php-league-commonmark-2.3.9/debian/patches/0003-Add-regression-test.patch	1970-01-01 01:00:00.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/patches/0003-Add-regression-test.patch	2026-03-26 08:15:50.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 968d780..af25950 100644
+--- a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php
++++ b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php
+@@ -71,6 +71,16 @@ final class DisallowedRawHtmlRendererTest extends TestCase
+         yield ['<script>', '&lt;script>'];
+         yield ['<plaintext>', '&lt;plaintext>'];
+ 
++        // Newline/whitespace bypass attempts (security fix)
++        yield ["<script   >", "&lt;script   >"];
++        yield ["<script\n>", "&lt;script\n>"];
++        yield ["<script\t>", "&lt;script\t>"];
++        yield ["<script\r\n>", "&lt;script\r\n>"];
++        yield ["<iframe\nwidth=\"560\">", "&lt;iframe\nwidth=\"560\">"];
++
++        // Ensure non-disallowed tags with similar names are NOT filtered
++        yield ['<scriptfoo>', '<scriptfoo>'];
++
+         // Tags not escaped by default
+         yield ['<strong>', '<strong>'];
+     }
+@@ -107,6 +117,11 @@ final class DisallowedRawHtmlRendererTest extends TestCase
+         yield ['<strong/>', '&lt;strong/>'];
+         yield ['<strong />', '&lt;strong />'];
+ 
++        // Newline bypass with custom config
++        yield ["<strong   >", "&lt;strong   >"];
++        yield ["<strong\n>", "&lt;strong\n>"];
++        yield ["<strong\t>", "&lt;strong\t>"];
++
+         // Defaults that I didn't include in my custom config
+         yield ['<title>', '<title>'];
+         yield ['<textarea>', '<textarea>'];
diff -Nru php-league-commonmark-2.3.9/debian/patches/0004-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch php-league-commonmark-2.3.9/debian/patches/0004-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch
--- php-league-commonmark-2.3.9/debian/patches/0004-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch	1970-01-01 01:00:00.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/patches/0004-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch	2026-03-26 08:15:50.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, '&lt;$1', $rendered);
+diff --git a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php
+index af25950..f8866e3 100644
+--- a/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php
++++ b/tests/unit/Extension/DisallowedRawHtml/DisallowedRawHtmlRendererTest.php
+@@ -72,7 +72,7 @@ final class DisallowedRawHtmlRendererTest extends TestCase
+         yield ['<plaintext>', '&lt;plaintext>'];
+ 
+         // Newline/whitespace bypass attempts (security fix)
+-        yield ["<script   >", "&lt;script   >"];
++        yield ['<script   >', '&lt;script   >'];
+         yield ["<script\n>", "&lt;script\n>"];
+         yield ["<script\t>", "&lt;script\t>"];
+         yield ["<script\r\n>", "&lt;script\r\n>"];
+@@ -118,7 +118,7 @@ final class DisallowedRawHtmlRendererTest extends TestCase
+         yield ['<strong />', '&lt;strong />'];
+ 
+         // Newline bypass with custom config
+-        yield ["<strong   >", "&lt;strong   >"];
++        yield ['<strong   >', '&lt;strong   >'];
+         yield ["<strong\n>", "&lt;strong\n>"];
+         yield ["<strong\t>", "&lt;strong\t>"];
+ 
diff -Nru php-league-commonmark-2.3.9/debian/patches/0005-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch php-league-commonmark-2.3.9/debian/patches/0005-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch
--- php-league-commonmark-2.3.9/debian/patches/0005-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch	1970-01-01 01:00:00.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/patches/0005-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch	2026-03-26 08:15:50.000000000 +0100
@@ -0,0 +1,106 @@
+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     | 38 ++++++++++++++--------
+ .../Extension/Embed/DomainFilteringAdapterTest.php | 18 ++++++++--
+ 2 files changed, 41 insertions(+), 15 deletions(-)
+
+diff --git a/src/Extension/Embed/DomainFilteringAdapter.php b/src/Extension/Embed/DomainFilteringAdapter.php
+index 69dc096..b00b028 100644
+--- a/src/Extension/Embed/DomainFilteringAdapter.php
++++ b/src/Extension/Embed/DomainFilteringAdapter.php
+@@ -17,15 +17,16 @@ class DomainFilteringAdapter implements EmbedAdapterInterface
+ {
+     private EmbedAdapterInterface $decorated;
+ 
+-    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);
+     }
+ 
+     /**
+@@ -33,18 +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
+-     */
+-    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.3.9/debian/patches/series php-league-commonmark-2.3.9/debian/patches/series
--- php-league-commonmark-2.3.9/debian/patches/series	2023-02-15 18:36:26.000000000 +0100
+++ php-league-commonmark-2.3.9/debian/patches/series	2026-03-26 08:15:50.000000000 +0100
@@ -1 +1,5 @@
 0001-Skip-tests-relying-on-packages-unavailable-in-Debian.patch
+0002-Fix-XSS-in-AttributesExtension.patch
+0003-Add-regression-test.patch
+0004-Fix-DisallowedRawHtml-bypass-via-newline-tab-in-tag-.patch
+0005-Fix-DomainFilteringAdapter-hostname-boundary-bypass.patch

Attachment: signature.asc
Description: PGP signature


--- End Message ---
--- Begin Message ---
Package: release.debian.org
Version: 12.14

This update has been released as part of Debian 12.14.

--- End Message ---

Reply via email to