Version in base suite: 2.7.0-1 Base version: dnspython_2.7.0-1 Target version: dnspython_2.7.0-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/d/dnspython/dnspython_2.7.0-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/d/dnspython/dnspython_2.7.0-1+deb13u1.dsc changelog | 10 + patches/0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch | 92 ++++++++++ patches/series | 1 3 files changed, 103 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp29a35lb0/dnspython_2.7.0-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp29a35lb0/dnspython_2.7.0-1+deb13u1.dsc: no acceptable signature found diff -Nru dnspython-2.7.0/debian/changelog dnspython-2.7.0/debian/changelog --- dnspython-2.7.0/debian/changelog 2024-12-01 20:23:40.000000000 +0000 +++ dnspython-2.7.0/debian/changelog 2026-10-24 12:34:30.000000000 +0000 @@ -1,3 +1,13 @@ +dnspython (2.7.0-1+deb13u1) trixie; urgency=medium + + * Backport upstream fix for CVE-2026-114605: limit DNS compression + pointer chains to 16 hops to prevent excessive CPU use (denial of + service) when parsing untrusted wire-format messages + (Closes: #1151842): + - 0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch + + -- Thomas Goirand Sat, 24 Oct 2026 14:34:30 +0200 + dnspython (2.7.0-1) unstable; urgency=medium * Team Upload diff -Nru dnspython-2.7.0/debian/patches/0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch dnspython-2.7.0/debian/patches/0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch --- dnspython-2.7.0/debian/patches/0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch 1970-01-01 00:00:00.000000000 +0000 +++ dnspython-2.7.0/debian/patches/0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch 2026-10-24 12:34:30.000000000 +0000 @@ -0,0 +1,92 @@ +Description: Limit decompression to a chain length of at most 16 pointers. + A maliciously crafted DNS message may cause dns.name.from_wire_parser() + to use excessive CPU for DNS name decompression. Applications which + process untrusted DNS wire form messages with dnspython may be degraded + or DoS'd by the extra CPU use required (CVE-2026-114605, + GHSA-45c3-73f7-pv4m). + . + Credit: Evgenios Gkritsis, Constantinos Patsakis and George + Stergiopoulos. +Author: Bob Halley +Date: Sat, 26 Sep 2026 13:38:07 -0700 +Origin: upstream, https://github.com/rthalley/dnspython/commit/b485e460c266540a1a09ca6d8d1d7b685b1d3023 +Bug: https://github.com/rthalley/dnspython/security/advisories/GHSA-45c3-73f7-pv4m +Bug-Debian: https://bugs.debian.org/1151842 +Last-Update: 2026-10-24 + +Index: dnspython/dns/name.py +=================================================================== +--- dnspython.orig/dns/name.py ++++ dnspython/dns/name.py +@@ -86,6 +86,10 @@ class BadPointer(dns.exception.FormError + """A DNS compression pointer points forward instead of backward.""" + + ++class PointerChainTooLong(dns.exception.FormError): ++ """A DNS compression pointer chain was too long.""" ++ ++ + class BadLabelType(dns.exception.FormError): + """The label type in DNS name wire format is unknown.""" + +@@ -1064,6 +1068,9 @@ def from_text( + return Name(labels) + + ++MAX_COMPRESSION_POINTER_CHAIN = 16 ++ ++ + # we need 'dns.wire.Parser' quoted as dns.name and dns.wire depend on each other. + + +@@ -1082,6 +1089,7 @@ def from_wire_parser(parser: "dns.wire.P + + labels = [] + biggest_pointer = parser.current ++ hops = 0 + with parser.restore_furthest(): + count = parser.get_uint8() + while count != 0: +@@ -1092,6 +1100,9 @@ def from_wire_parser(parser: "dns.wire.P + if current >= biggest_pointer: + raise BadPointer + biggest_pointer = current ++ hops += 1 ++ if hops > MAX_COMPRESSION_POINTER_CHAIN: ++ raise PointerChainTooLong + parser.seek(current) + else: + raise BadLabelType +Index: dnspython/tests/test_name.py +=================================================================== +--- dnspython.orig/tests/test_name.py ++++ dnspython/tests/test_name.py +@@ -739,6 +739,28 @@ class NameTestCase(unittest.TestCase): + + self.assertRaises(dns.name.BadLabelType, bad) + ++ def testCompressionChainLength(self): ++ # We're going to decode some wire starting two bytes from the end. At this ++ # position is a pointer which points to four bytes from the end, and it points ++ # to one 6 bytes from the end, etc., until finally the 16th pointer points at ++ # offset zero, which is the root label followed by a byte of padding. After ++ # all of this useless pointer hopping, we should get the root name. ++ w = b"\x00\x00\xc0\x00\xc0\x02\xc0\x04\xc0\x06\xc0\x08\xc0\x0a\xc0\x0c\xc0\x0e\xc0\x10\xc0\x12\xc0\x14\xc0\x16\xc0\x18\xc0\x1a\xc0\x1c\xc0\x1e" ++ self.assertEqual(len(w), 34) ++ starts = [c for c in w if c == 0xC0] ++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN) ++ ++ def bad(): ++ # Now we make the wire one pointer longer, which is too long! ++ w1 = w + b"\xc0\x20" ++ self.assertEqual(len(w1), 36) ++ starts = [c for c in w1 if c == 0xC0] ++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN + 1) ++ dns.name.from_wire(w1, 34) ++ ++ self.assertEqual(dns.name.from_wire(w, 32)[0], dns.name.from_text(".")) ++ self.assertRaises(dns.name.PointerChainTooLong, bad) ++ + def testParent1(self): + n = dns.name.from_text("foo.bar.") + self.assertEqual(n.parent(), dns.name.from_text("bar.")) diff -Nru dnspython-2.7.0/debian/patches/series dnspython-2.7.0/debian/patches/series --- dnspython-2.7.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ dnspython-2.7.0/debian/patches/series 2026-10-24 12:34:30.000000000 +0000 @@ -0,0 +1 @@ +0001-Limit-decompression-to-a-chain-length-of-at-most-16-.patch