Your message dated Fri, 15 May 2026 17:49:03 +0100
with message-id 
<d6238dc7802aea4e0cadad3e3b98a7edef95398c.ca...@adam-barratt.org.uk>
and subject line Re: Bug#1136746: bullseye-pu: package beets/1.4.9-7+deb11u1
has caused the Debian Bug report #1136746,
regarding bullseye-pu: package beets/1.4.9-7+deb11u1
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.)


-- 
1136746: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1136746
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
X-Debbugs-Cc: [email protected]

Package: release.debian.org
Tags: bullseye
X-Debbugs-Cc: [email protected], [email protected]
Control: affects -1 + src:beets
User: [email protected]
Usertags: pu

Fix CVE-2026-42052 and #1135779

[ Reason ]
CVE is considered low risk, no DSA, and fixable by production update.

[ Impact ]
CVE remains unfixed.

[ Tests ]
Added a test in patch add_unit_test_checking_unsafe_web_ui_input to check the
CVE is fixed.
test/plugins/test_web.py should give assurance against regressions.

[ Risks ]
Regression in web ui plugin, but existing tests should cover this.

[ 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
  [ ] the issue is verified as fixed in unstable

[ Changes ]
All input fields in the web ui js template are using escaping syntax (<%- %)
instead of the non-escaping syntax (<%= %)

Two unrelated tests are broken today, which I suppose were not broken back in 
the
day when beets was at 1.4.9-7. I did not see a reason or solution right away
and decided to skip them with d/p/skip-broken-tests-1.4.9-7+deb11.

[ Other info ]
I'm not a DD, I won't be uploading myself. I will probably be continuing work
with eamanu who did a first review.

My fix for unstable is also waiting review/upload.
diff -Nru beets-1.4.9/debian/changelog beets-1.4.9/debian/changelog
--- beets-1.4.9/debian/changelog        2020-08-12 20:28:00.000000000 +0200
+++ beets-1.4.9/debian/changelog        2026-05-14 20:15:07.000000000 +0200
@@ -1,3 +1,9 @@
+beets (1.4.9-7+deb11u1) UNRELEASED; urgency=medium
+
+  * Add patches for CVE-2026-42052 to bullseye (Closes: #1135779)
+
+ -- Pieter Lenaerts <[email protected]>  Thu, 14 May 2026 20:15:07 +0200
+
 beets (1.4.9-7) unstable; urgency=medium
 
   * Bump Build-Depends on python3-mutagen, to help the migration autopkgtests.
diff -Nru beets-1.4.9/debian/patches/2025-future 
beets-1.4.9/debian/patches/2025-future
--- beets-1.4.9/debian/patches/2025-future      1970-01-01 01:00:00.000000000 
+0100
+++ beets-1.4.9/debian/patches/2025-future      2026-05-14 20:15:07.000000000 
+0200
@@ -0,0 +1,37 @@
+From: Pieter Lenaerts <[email protected]>
+Date: Mon, 11 May 2026 20:32:39 +0200
+Subject: Future proof BucketPluginTest.test_year_single_year_last_folder
+
+This test assumes 2025 is in the future. It used to be.
+
+This is a backport from Stefano's patch in tag debian/2.2.0-2
+
+Forwarded: not-needed
+Origin: 
https://salsa.debian.org/python-team/packages/beets/-/blob/debian/2.2.0-2/debian/patches/2025-future?ref_type=tags
+---
+ test/test_bucket.py | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/test/test_bucket.py b/test/test_bucket.py
+index 61f6cfe..3a265ab 100644
+--- a/test/test_bucket.py
++++ b/test/test_bucket.py
+@@ -23,6 +23,7 @@ from beets import config, ui
+ 
+ from test.helper import TestHelper
+ 
++from datetime import datetime
+ 
+ class BucketPluginTest(unittest.TestCase, TestHelper):
+     def setUp(self):
+@@ -52,7 +53,9 @@ class BucketPluginTest(unittest.TestCase, TestHelper):
+         year."""
+         self._setup_config(bucket_year=['1950', '1970'])
+         self.assertEqual(self.plugin._tmpl_bucket('2014'), '1970')
+-        self.assertEqual(self.plugin._tmpl_bucket('2025'), '2025')
++        next_year = datetime.now().year + 1
++        self.assertEqual(self.plugin._tmpl_bucket(str(next_year)),
++                         str(next_year))
+ 
+     def test_year_two_years(self):
+         """Buckets can be named with the 'from-to' syntax."""
diff -Nru beets-1.4.9/debian/patches/add_unit_test_checking_unsafe_web_ui_input 
beets-1.4.9/debian/patches/add_unit_test_checking_unsafe_web_ui_input
--- beets-1.4.9/debian/patches/add_unit_test_checking_unsafe_web_ui_input       
1970-01-01 01:00:00.000000000 +0100
+++ beets-1.4.9/debian/patches/add_unit_test_checking_unsafe_web_ui_input       
2026-05-14 20:15:07.000000000 +0200
@@ -0,0 +1,100 @@
+From: Pieter Lenaerts <[email protected]>
+Date: Sat, 9 May 2026 12:22:05 +0200
+Subject: Add unit test checking for unsafe input in web ui
+
+Forwarded: https://github.com/beetbox/beets/pull/6639
+---
+ test/plugins/test_web_xss.py | 84 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+ create mode 100644 test/plugins/test_web_xss.py
+
+diff --git a/test/plugins/test_web_xss.py b/test/plugins/test_web_xss.py
+new file mode 100644
+index 0000000..2743489
+--- /dev/null
++++ b/test/plugins/test_web_xss.py
+@@ -0,0 +1,84 @@
++"""Tests for XSS vulnerability in the web plugin templates.
++
++This test verifies that the Underscore.js templates in index.html use
++the escaping syntax (<%- %) instead of the non-escaping syntax (<%= %).
++
++In Underscore.js 1.2.2 (used by beets):
++- <%= variable %> does NOT escape HTML (vulnerable to XSS)
++- <%- variable %> DOES escape HTML (safe)
++
++The test checks the index.html template file served by Flask to ensure
++all user data interpolations in the Underscore.js templates use the escaping
++syntax.
++
++Generated using mistral vibe, verified by Pieter Lenaerts <[email protected]>
++"""
++
++import re
++
++from test import _common
++from beetsplug import web
++
++
++class WebXSSTest(_common.LibTestCase):
++    def setUp(self):
++        super().setUp()
++        web.app.config['TESTING'] = True
++        web.app.config['lib'] = self.lib
++        web.app.config['INCLUDE_PATHS'] = False
++        web.app.config['READONLY'] = True
++        self.client = web.app.test_client()
++
++    def test_templates_use_escaping_syntax(self):
++        """Verify that all Underscore.js templates use <%- %> for escaping.
++
++        This test requests the index.html page and checks that all
++        user data interpolations in the Underscore.js templates use
++        the escaping syntax (<%- %) rather than the non-escaping syntax (<%= 
%).
++
++        Before the fix (with <%= %>), this test will fail.
++        After the fix (with <%- %>), this test will pass.
++        """
++        # Request the index.html page
++        response = self.client.get("/")
++        html = response.data.decode("utf-8")
++
++        # Extract the template scripts from the HTML
++        # The templates are in <script type="text/template"> blocks
++        template_pattern = r'<script type="text/template"[^>]*>(.*?)</script>'
++        templates = re.findall(template_pattern, html, re.DOTALL)
++
++        # Combine all template content for checking
++        all_template_content = "\n".join(templates)
++
++        # Check that no <%= %> (non-escaping) tags exist for user data
++        # We look for <%= followed by a variable name (word characters)
++        non_escaping_pattern = r'<%=\s*(\w+)\s*%>'
++        non_escaping_matches = re.findall(non_escaping_pattern, 
all_template_content)
++
++        # List of fields that should be escaped (user-controlled data)
++        user_data_fields = [
++            'title', 'artist', 'album', 'year', 'track', 'tracktotal',
++            'disc', 'disctotal', 'length', 'format', 'bitrate',
++            'mb_trackid', 'id', 'lyrics', 'comments'
++        ]
++
++        # Check if any user data fields are using non-escaping <%= %>
++        vulnerable_fields = [field for field in non_escaping_matches if field 
in user_data_fields]
++
++        # If we found any user data fields using <%= %>, the templates are 
vulnerable
++        assert len(vulnerable_fields) == 0, (
++            f"Found non-escaping <%= %> tags for user data fields: 
{vulnerable_fields}. "
++            f"These should use <%- %> for HTML escaping to prevent XSS."
++        )
++
++        # Also verify that escaping tags (<%- %>) are present for user data
++        escaping_pattern = r'<%-\s*(\w+)\s*%>'
++        escaping_matches = re.findall(escaping_pattern, all_template_content)
++
++        # At least some user data fields should use escaping
++        safe_fields = [field for field in escaping_matches if field in 
user_data_fields]
++        assert len(safe_fields) > 0, (
++            "No escaping <%- %> tags found for user data fields. "
++            "Templates should use <%- %> for HTML escaping."
++        )
diff -Nru 
beets-1.4.9/debian/patches/fix_xss_by_using_escaped_template_tags_in_web_ui 
beets-1.4.9/debian/patches/fix_xss_by_using_escaped_template_tags_in_web_ui
--- beets-1.4.9/debian/patches/fix_xss_by_using_escaped_template_tags_in_web_ui 
1970-01-01 01:00:00.000000000 +0100
+++ beets-1.4.9/debian/patches/fix_xss_by_using_escaped_template_tags_in_web_ui 
2026-05-14 20:15:07.000000000 +0200
@@ -0,0 +1,82 @@
+From: Šarūnas Nejus https://github.com/snejus
+Date: Sat, 9 May 2026 08:04:44 +0200
+Subject: Fix XSS by using escaped template tags in web UI
+
+Bug: https://github.com/beetbox/beets/security/advisories/GHSA-3gxm-wfjx-m847
+Bug-Debian: https://bugs.debian.org/1135779
+Origin: backport, 
https://github.com/beetbox/beets/commit/75f0d8f4899e61afb939adf02dcfb078aed23a6a
+Forwarded: not-needed
+---
+ beetsplug/web/templates/index.html | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/beetsplug/web/templates/index.html 
b/beetsplug/web/templates/index.html
+index 0fdd46d..7b1e43f 100644
+--- a/beetsplug/web/templates/index.html
++++ b/beetsplug/web/templates/index.html
+@@ -45,16 +45,16 @@
+ 
+         <!-- Templates. -->
+         <script type="text/template" id="item-entry-template">
+-            <%= title %>
++            <%- title %>
+             <span class="playing">&#9654;</span>
+         </script>
+         <script type="text/template" id="item-main-detail-template">
+-            <span class="artist"><%= artist %></span>
++            <span class="artist"><%- artist %></span>
+             <span class="album">
+-                <span class="albumtitle"><%= album %></span>
+-                <span class="year">(<%= year %>)</span>
++                <span class="albumtitle"><%- album %></span>
++                <span class="year">(<%- year %>)</span>
+             </span>
+-            <span class="title"><%= title %></span>
++            <span class="title"><%- title %></span>
+ 
+             <button class="play">&#9654;</button>
+ 
+@@ -63,34 +63,34 @@
+         <script type="text/template" id="item-extra-detail-template">
+             <dl>
+                 <dt>Track</dt>
+-                <dd><%= track %>/<%= tracktotal %></dd>
++                <dd><%- track %>/<%- tracktotal %></dd>
+                 <% if (disc) { %>
+                     <dt>Disc</dt>
+-                    <dd><%= disc %>/<%= disctotal %></dd>
++                    <dd><%- disc %>/<%- disctotal %></dd>
+                 <% } %>
+                 <dt>Length</dt>
+-                <dd><%= timeFormat(length) %></dd>
++                <dd><%- timeFormat(length) %></dd>
+                 <dt>Format</dt>
+-                <dd><%= format %></dd>
++                <dd><%- format %></dd>
+                 <dt>Bitrate</dt>
+-                <dd><%= Math.round(bitrate/1000) %> kbps</dd>
++                <dd><%- Math.round(bitrate/1000) %> kbps</dd>
+                 <% if (mb_trackid) { %>
+                     <dt>MusicBrainz entry</dt>
+                     <dd>
+-                        <a target="_blank" 
href="http://musicbrainz.org/recording/<%= mb_trackid %>">view</a>
++                        <a target="_blank" 
href="http://musicbrainz.org/recording/<%- mb_trackid %>">view</a>
+                     </dd>
+                 <% } %>
+                 <dt>File</dt>
+                 <dd>
+-                    <a target="_blank" class="download" href="item/<%= id 
%>/file">download</a>
++                    <a target="_blank" class="download" href="item/<%- id 
%>/file">download</a>
+                 </dd>
+                 <% if (lyrics) { %>
+                     <dt>Lyrics</dt>
+-                    <dd class="lyrics"><%= lyrics %></dd>
++                    <dd class="lyrics"><%- lyrics %></dd>
+                 <% } %>
+                 <% if (comments) { %>
+                     <dt>Comments</dt>
+-                    <dd><%= comments %></dd>
++                    <dd><%- comments %></dd>
+                 <% } %>
+             </dl>
+         </script>
diff -Nru beets-1.4.9/debian/patches/series beets-1.4.9/debian/patches/series
--- beets-1.4.9/debian/patches/series   2020-08-12 20:28:00.000000000 +0200
+++ beets-1.4.9/debian/patches/series   2026-05-14 20:15:07.000000000 +0200
@@ -6,3 +6,7 @@
 python-3.8-ast
 werkzeug-1.0
 mutagen-1.45
+fix_xss_by_using_escaped_template_tags_in_web_ui
+add_unit_test_checking_unsafe_web_ui_input
+2025-future
+skip-broken-tests-1.4.9-7+deb11
diff -Nru beets-1.4.9/debian/patches/skip-broken-tests-1.4.9-7+deb11 
beets-1.4.9/debian/patches/skip-broken-tests-1.4.9-7+deb11
--- beets-1.4.9/debian/patches/skip-broken-tests-1.4.9-7+deb11  1970-01-01 
01:00:00.000000000 +0100
+++ beets-1.4.9/debian/patches/skip-broken-tests-1.4.9-7+deb11  2026-05-14 
20:15:07.000000000 +0200
@@ -0,0 +1,29 @@
+From: Pieter Lenaerts <[email protected]>
+Date: Mon, 11 May 2026 20:52:37 +0200
+Subject: Skip broken tests
+
+Forwarded: not-needed
+---
+ test/test_ui.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/test/test_ui.py b/test/test_ui.py
+index 3cc0caa..0c5448b 100644
+--- a/test/test_ui.py
++++ b/test/test_ui.py
+@@ -775,6 +775,7 @@ class ConfigTest(unittest.TestCase, TestHelper, 
_common.Assertions):
+         self.assertEqual(key, 'x')
+         self.assertEqual(template.original, 'y')
+ 
++    @unittest.skip("Broken")
+     def test_default_paths_preserved(self):
+         default_formats = ui.get_path_formats()
+ 
+@@ -883,6 +884,7 @@ class ConfigTest(unittest.TestCase, TestHelper, 
_common.Assertions):
+ #                      '--config', cli_overwrite_config_path, 'test')
+ #        self.assertEqual(config['anoption'].get(), 'cli overwrite')
+ 
++    @unittest.skip("Broken")
+     def test_cli_config_paths_resolve_relative_to_user_dir(self):
+         cli_config_path = os.path.join(self.temp_dir, b'config.yaml')
+         with open(cli_config_path, 'w') as file:

--- End Message ---
--- Begin Message ---
Hi,

On Fri, 2026-05-15 at 18:40 +0200, Pieter Lenaerts wrote:
> Package: release.debian.org
> Tags: bullseye
> X-Debbugs-Cc: [email protected], [email protected]
> Control: affects -1 + src:beets
> User: [email protected]
> Usertags: pu
> 
> Fix CVE-2026-42052 and #1135779

The Release Team hasn't managed bullseye for nearly two years now.

Please co-ordinate with the LTS Team (CCed) for any updates in
bullseye. I'm going to close the release.debian.org bug with this
message.

Regards,

Adam

--- End Message ---

Reply via email to