Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:lxml
User: [email protected]
Usertags: pu

[ Reason ]

Fix <no-dsa> issues CVE-2026-41066 and CVE-2026-49825.

[ Impact ]

Users will remain vulnerable to these issues, and will regress when
upgrading (a fix will be uploaded to Bookworm LTS shortly).

[ Tests ]

POC at https://bugs.launchpad.net/lxml/+bug/2146291 and
https://github.com/fedora-python/lxml_html_clean/security/advisories/GHSA-4jhm-jv67-739f
and manual test suite run (the test suite is not run at build time, see
#976148).

[ Risks ]

Trivial fixes.

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

[ Changes ]

  * Fix CVE-2026-41066: Default configuration of iterparse() and
    ETCompatXMLParser() allows XXE to local files.
    This update changes the default to resolve_entities='internal' (hence
    disallowing local file access by default).
  * Fix CVE-2026-49825: URL bypass in Cleaner via xlink:href.
  * Add d/salsa-ci.yml for Salsa CI.
  * Re-generate .c files.

[ Other info ]

The attached debdiff excludes the d/p/Update-.c-files.patch patch which
updates the generated .c files (the package is built without cython, so
.c files need to be regenerated and the result saved in d/patches).  I
attach that file gzipped separately anyway.

Debusine workflow output:
https://debusine.debian.net/debian/developers/work-request/1367042/

Individual commits and tag can be found on the LTS team fork at
https://salsa.debian.org/lts-team/packages/lxml/-/tree/debian/trixie?ref_type=heads

-- 
Guilhem.
diffstat for lxml-5.4.0 lxml-5.4.0

 changelog                    |   13 ++++++
 patches/CVE-2026-41066.patch |   82 +++++++++++++++++++++++++++++++++++++++++++
 patches/CVE-2026-49825.patch |   26 +++++++++++++
 patches/series               |    3 +
 salsa-ci.yml                 |    8 ++++
 5 files changed, 132 insertions(+)

diff -Nru --exclude Update-.c-files.patch lxml-5.4.0/debian/changelog 
lxml-5.4.0/debian/changelog
--- lxml-5.4.0/debian/changelog 2025-05-03 17:06:29.000000000 +0200
+++ lxml-5.4.0/debian/changelog 2026-09-28 17:51:59.000000000 +0200
@@ -1,3 +1,16 @@
+lxml (5.4.0-1+deb13u1) trixie; urgency=high
+
+  * Non-maintainer upload.
+  * Fix CVE-2026-41066: Default configuration of iterparse() and
+    ETCompatXMLParser() allows XXE to local files. (LP: #2146291)
+    This update changes the default to resolve_entities='internal' (hence
+    disallowing local file access by default).
+  * Fix CVE-2026-49825: URL bypass in Cleaner via xlink:href.
+  * Add d/salsa-ci.yml for Salsa CI.
+  * Re-generate .c files.
+
+ -- Guilhem Moulin <[email protected]>  Mon, 28 Sep 2026 17:51:59 +0200
+
 lxml (5.4.0-1) unstable; urgency=medium
 
   * New upstream version (no source changes).
diff -Nru --exclude Update-.c-files.patch 
lxml-5.4.0/debian/patches/CVE-2026-41066.patch 
lxml-5.4.0/debian/patches/CVE-2026-41066.patch
--- lxml-5.4.0/debian/patches/CVE-2026-41066.patch      1970-01-01 
01:00:00.000000000 +0100
+++ lxml-5.4.0/debian/patches/CVE-2026-41066.patch      2026-09-28 
17:51:59.000000000 +0200
@@ -0,0 +1,82 @@
+From: Stefan Behnel <[email protected]>
+Date: Fri, 10 Apr 2026 10:13:03 +0200
+Subject: LP#2146291: Set "resolve_entities='internal'" as default for all
+ parser subclasses.
+
+Origin: 
https://github.com/lxml/lxml/commit/ab431ea0b9a7357d968f1d1c5c614649e9aaf358
+Bug: https://github.com/lxml/lxml/security/advisories/GHSA-vfmq-68hx-4jfw
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-41066
+Bug-Ubuntu: https://bugs.launchpad.net/lxml/+bug/2146291
+---
+ src/lxml/iterparse.pxi | 10 ++++++----
+ src/lxml/parser.pxi    |  6 +++---
+ 2 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/src/lxml/iterparse.pxi b/src/lxml/iterparse.pxi
+index 42b7524..9b6ceb0 100644
+--- a/src/lxml/iterparse.pxi
++++ b/src/lxml/iterparse.pxi
+@@ -6,7 +6,8 @@ cdef class iterparse:
+     """iterparse(self, source, events=("end",), tag=None, \
+                   attribute_defaults=False, dtd_validation=False, \
+                   load_dtd=False, no_network=True, remove_blank_text=False, \
+-                  remove_comments=False, remove_pis=False, encoding=None, \
++                  compact=True, resolve_entities='internal', 
remove_comments=False, \
++                  remove_pis=False, strip_cdata=True, encoding=None, \
+                   html=False, recover=None, huge_tree=False, schema=None)
+ 
+     Incremental parser.
+@@ -42,10 +43,11 @@ cdef class iterparse:
+      - remove_blank_text: discard blank text nodes
+      - remove_comments: discard comments
+      - remove_pis: discard processing instructions
+-     - strip_cdata: replace CDATA sections by normal text content (default: 
++     - strip_cdata: replace CDATA sections by normal text content (default:
+        True for XML, ignored otherwise)
+      - compact: safe memory for short text content (default: True)
+-     - resolve_entities: replace entities by their text value (default: True)
++     - resolve_entities: replace entities by their text value
++       (default: 'internal' only)
+      - huge_tree: disable security restrictions and support very deep trees
+                   and very long text content (only affects libxml2 2.7+)
+      - html: parse input as HTML (default: XML)
+@@ -68,7 +70,7 @@ cdef class iterparse:
+     def __init__(self, source, events=("end",), *, tag=None,
+                  attribute_defaults=False, dtd_validation=False,
+                  load_dtd=False, no_network=True, remove_blank_text=False,
+-                 compact=True, resolve_entities=True, remove_comments=False,
++                 compact=True, resolve_entities='internal', 
remove_comments=False,
+                  remove_pis=False, strip_cdata=True, encoding=None,
+                  html=False, recover=None, huge_tree=False, collect_ids=True,
+                  XMLSchema schema=None):
+diff --git a/src/lxml/parser.pxi b/src/lxml/parser.pxi
+index 70337d8..ef54306 100644
+--- a/src/lxml/parser.pxi
++++ b/src/lxml/parser.pxi
+@@ -1550,7 +1550,7 @@ _XML_DEFAULT_PARSE_OPTIONS = (
+     )
+ 
+ cdef class XMLParser(_FeedParser):
+-    """XMLParser(self, encoding=None, attribute_defaults=False, 
dtd_validation=False, load_dtd=False, no_network=True, ns_clean=False, 
recover=False, schema: XMLSchema =None, huge_tree=False, 
remove_blank_text=False, resolve_entities=True, remove_comments=False, 
remove_pis=False, strip_cdata=True, collect_ids=True, target=None, compact=True)
++    """XMLParser(self, encoding=None, attribute_defaults=False, 
dtd_validation=False, load_dtd=False, no_network=True, ns_clean=False, 
recover=False, schema: XMLSchema =None, huge_tree=False, 
remove_blank_text=False, resolve_entities='internal', remove_comments=False, 
remove_pis=False, strip_cdata=True, collect_ids=True, target=None, compact=True)
+ 
+     The XML parser.
+ 
+@@ -1672,7 +1672,7 @@ cdef class ETCompatXMLParser(XMLParser):
+     """ETCompatXMLParser(self, encoding=None, attribute_defaults=False, \
+                  dtd_validation=False, load_dtd=False, no_network=True, \
+                  ns_clean=False, recover=False, schema=None, \
+-                 huge_tree=False, remove_blank_text=False, 
resolve_entities=True, \
++                 huge_tree=False, remove_blank_text=False, 
resolve_entities='internal', \
+                  remove_comments=True, remove_pis=True, strip_cdata=True, \
+                  target=None, compact=True)
+ 
+@@ -1686,7 +1686,7 @@ cdef class ETCompatXMLParser(XMLParser):
+     def __init__(self, *, encoding=None, attribute_defaults=False,
+                  dtd_validation=False, load_dtd=False, no_network=True,
+                  ns_clean=False, recover=False, schema=None,
+-                 huge_tree=False, remove_blank_text=False, 
resolve_entities=True,
++                 huge_tree=False, remove_blank_text=False, 
resolve_entities='internal',
+                  remove_comments=True, remove_pis=True, strip_cdata=True,
+                  target=None, compact=True):
+         XMLParser.__init__(self,
diff -Nru --exclude Update-.c-files.patch 
lxml-5.4.0/debian/patches/CVE-2026-49825.patch 
lxml-5.4.0/debian/patches/CVE-2026-49825.patch
--- lxml-5.4.0/debian/patches/CVE-2026-49825.patch      1970-01-01 
01:00:00.000000000 +0100
+++ lxml-5.4.0/debian/patches/CVE-2026-49825.patch      2026-09-28 
17:51:59.000000000 +0200
@@ -0,0 +1,26 @@
+From: Stefan Behnel <[email protected]>
+Date: Sun, 17 May 2026 21:42:51 +0200
+Subject: Add missing "xlink:href" to the known HTML link attributes.
+
+Origin: 
https://github.com/lxml/lxml/commit/5927a6d5e851845140975d99b65461e255caaab0
+Bug: 
https://github.com/fedora-python/lxml_html_clean/security/advisories/GHSA-4jhm-jv67-739f
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-49825
+---
+ src/lxml/html/defs.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/lxml/html/defs.py b/src/lxml/html/defs.py
+index 2058ea3..2c8dfa2 100644
+--- a/src/lxml/html/defs.py
++++ b/src/lxml/html/defs.py
+@@ -24,7 +24,9 @@ link_attrs = frozenset([
+     # Not standard:
+     'dynsrc', 'lowsrc',
+     # HTML5 formaction
+-    'formaction'
++    'formaction',
++    # XLink as used by HTML5 (including embedded SVG/MathML)
++    'xlink:href',
+     ])
+ 
+ # Not in the HTML 4 spec:
diff -Nru --exclude Update-.c-files.patch lxml-5.4.0/debian/patches/series 
lxml-5.4.0/debian/patches/series
--- lxml-5.4.0/debian/patches/series    2021-09-15 12:53:52.000000000 +0200
+++ lxml-5.4.0/debian/patches/series    2026-09-28 17:51:59.000000000 +0200
@@ -1 +1,4 @@
 do-not-embed-timestamps-in-html.diff
+CVE-2026-41066.patch
+CVE-2026-49825.patch
+Update-.c-files.patch
diff -Nru --exclude Update-.c-files.patch lxml-5.4.0/debian/salsa-ci.yml 
lxml-5.4.0/debian/salsa-ci.yml
--- lxml-5.4.0/debian/salsa-ci.yml      1970-01-01 01:00:00.000000000 +0100
+++ lxml-5.4.0/debian/salsa-ci.yml      2026-09-28 17:51:59.000000000 +0200
@@ -0,0 +1,8 @@
+---
+include:
+  - 
https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
+
+variables:
+  RELEASE: 'trixie'
+  SALSA_CI_DISABLE_REPROTEST: 1
+  SALSA_CI_DISABLE_USCAN: 1

Attachment: Update-.c-files.patch.gz
Description: application/gzip

Attachment: signature.asc
Description: PGP signature

Reply via email to