changelog-9.20.26.rst revision 1.1 1 .. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2 ..
3 .. SPDX-License-Identifier: MPL-2.0
4 ..
5 .. This Source Code Form is subject to the terms of the Mozilla Public
6 .. License, v. 2.0. If a copy of the MPL was not distributed with this
7 .. file, you can obtain one at https://mozilla.org/MPL/2.0/.
8 ..
9 .. See the COPYRIGHT file distributed with this work for additional
10 .. information regarding copyright ownership.
11
12 BIND 9.20.26
13 ------------
14
15 Security Fixes
16 ~~~~~~~~~~~~~~
17
18 - [CVE-2026-11331] Fix handling of rpz CNAME expansion that returns name
19 too long. ``b950da5f625``
20
21 Previously, if the expansion of a wildcard CNAME RPZ policy resulted
22 in a name that exceeded the length limit, a self referential CNAME and
23 the original address record were returned, allowing the policy to be
24 bypassed. In branches up to 9.20, this also left query processing in
25 an inconsistent state which could trigger an assertion failure. We
26 now return a YXDOMAIN response, without the address.
27
28 ISC would like to thank Laith Mash'al (0xmshal) for bringing this
29 issue to our attention. :gl:`#5856`
30
31 - [CVE-2026-11721] Invalid signed wildcard records were being accepted.
32 ``249752cd72d``
33
34 Signed wildcard responses in which the Labels field in the `RRSIG`
35 record was less than the number of labels in the Signer Name field
36 were being incorrectly accepted. This in turn broke
37 `synth-from-dnssec`, which depends on such records being correctly
38 validated. This has been fixed.
39
40 ISC thanks Qifan Zhang of Palo Alto Networks for bringing this issue
41 to our attention. :gl:`#5871`
42
43 - [CVE-2026-13321] Fix DNSSEC validation bypass via out-of-zone NSEC
44 Next Field. ``6fbc963d4af``
45
46 A malicious zone with out-of-zone NSEC next owner names can cause a
47 DNSSEC validating resolver to cache such record and, if
48 `synth-from-dnssec` is enabled, to generate negative answers for any
49 zone that is covered by the range.
50
51 ISC would like to thank Qifan Zhang of Palo Alto Networks for
52 reporting the issue. :gl:`#5873`
53
54 - [CVE-2026-10723] Correct verification of NSEC3 signer name.
55 ``df3abfc3184``
56
57 BIND 9 accepted child-zone NSEC3 records where the first label equals
58 the hash of the parent zone as valid parent-zone closest encloser
59 proofs. This has been fixed.
60
61 ISC thanks Qifan Zhang of Palo Alto Networks for reporting the issue.
62 :gl:`#5874`
63
64 - [CVE-2026-12617] Do no assert for some specifics CNAME and DNAME
65 queries. ``d75d1e93958``
66
67 A bug in the resolver's handling of certain cached DNAME and CNAME
68 responses could cause named to trigger an assertion failure and exit.
69 An attacker controlling a domain name and the authoritative DNS server
70 it is hosted on could exploit this behavior to cause a
71 denial-of-service. This vulnerability has been fixed.
72
73 ISC thanks Qifan Zhang of Palo Alto Networks for bringing this issue
74 to our attention. :gl:`#5946`
75
76 - [CVE-2026-10822] Malformed DNSKEY records could trigger an assertion.
77 ``a1777ce7ee0``
78
79 Previously, `dns_name_fromwire()` did not honor the record boundary
80 when reading names from the wire, allowing malformed records to be
81 accepted when they should not have been. In particular, malformed
82 DNSKEY records could trigger an assertion failure when being printed.
83 This has been fixed. :gl:`#6004`
84
85 - Reclaim memory promptly when DNSSEC validations are canceled.
86 ``b8f9d7657ac``
87
88 When a resolver is flooded with queries that require DNSSEC validation
89 for example during a random-subdomain attack many of those
90 validations are canceled before they complete. Previously a canceled
91 validation still kept its place in the internal work queue and held
92 the associated response in memory until that queued work eventually
93 ran, so memory could climb sharply under sustained load. The canceled
94 work is now dropped as soon as the validation is canceled, releasing
95 the memory it was holding.
96
97 - [CVE-2026-11605] Prevent excessive validation work from crafted
98 negative responses. ``5f1bb0aad09``
99
100 A validating resolver could be made to perform a large amount of
101 DNSSEC validation work in response to a single answer, consuming
102 excessive CPU. A malicious authoritative server triggers this by
103 returning a signed negative answer (NXDOMAIN or NODATA) padded with
104 many denial-of-existence proof records, which the resolver continued
105 to verify beyond its per-query validation limit. It now enforces that
106 limit on negative answers and returns SERVFAIL once the limit is
107 reached.
108
109 Closes: https://gitlab.isc.org/isc-projects/bind9/-/work_items/4463
110
111 - [CVE-2026-11622] Prevent cache exhaustion under sustained attack.
112 ``410aa215eab``
113
114 The cache memory can become exhausted with expired entries whose
115 memory is not released due to a sustained attack on the same DNS name
116 that prevents the cleanup. This has been fixed.
117
118 Closes: https://gitlab.isc.org/isc-projects/bind9/-/work_items/4760
119
120 New Features
121 ~~~~~~~~~~~~
122
123 - Print OS platform in "named -V" ``5bb30b1f993``
124
125 The "running on" line emitted by `named -V` (as well as the startup
126 log and `rndc status`, which share the same source) now appends the
127 PRETTY_NAME value from /etc/os-release in parentheses after the uname
128 output, e.g.:
129
130 running on Linux x86_64 6.19.14-... (Fedora Linux 42 (Workstation
131 Edition))
132
133 This helps disambiguate environments where the kernel string is not a
134 reliable indicator of the userspace, such as RHEL clones and
135 containers whose kernel does not match the host OS.
136
137 When /etc/os-release is absent, /usr/lib/os-release is tried as a
138 fallback per the systemd os-release(5) specification. When neither is
139 available or no PRETTY_NAME is found, the output is unchanged.
140
141 Assisted-by: Claude:claude-opus-4-7 :gl:`#5334` :gl:`!12319`
142
143 Removed Features
144 ~~~~~~~~~~~~~~~~
145
146 - Remove the secondary validator in query.c. ``1687a3d0b85``
147
148 Previously, when the additional section of a response was being
149 populated, if cached data was found with pending trust, it would be
150 opportunistically validated. The code implementing this validation was
151 not quite formally correct. Rather than fixing it, the code has been
152 removed: RRsets with pending trust are now omitted from responses.
153 :gl:`#5966` :gl:`#5968` :gl:`#5972` :gl:`!12258`
154
155 Feature Changes
156 ~~~~~~~~~~~~~~~
157
158 - Rework isc_work as per-loop, per-lane cancelable worker threads.
159 ``51d67c173e9``
160
161 Fold the libuv thread pool and the per-loop isc_helper threads into a
162 single isc_work pool. Each (loop, lane) gets its own SPSC queue and
163 worker, which drops the shared-queue contention, and the FAST/SLOW
164 lanes keep short crypto tasks off the long blocking ones (zone
165 dump/load, xfrin). isc_work jobs are now cancelable: isc_work_cancel()
166 tombstones a still-queued job and its after_cb fires with
167 ISC_R_CANCELED, so abandoned work can be dropped instead of run to
168 completion. :gl:`!12267`
169
170 - Sync picohttpparser.c with upstream commit a875a01. ``7b249a11e34``
171
172 Synced with the h2o/picohttpparser upstream repository up to commit
173 f4d94b48b31e0abae029ebeafcfd9ca0680ede58.
174
175 This commit is just hygiene and consistency by keeping the vendored
176 copy current. :gl:`!12273`
177
178 Bug Fixes
179 ~~~~~~~~~
180
181 - Fix a bug in DNS UPDATE processing with inline-signing enabled.
182 ``ad4650c78fa``
183
184 In rare cases the :iscman:`named` process could terminate unexpectedly
185 when processing authorized DNS UPDATE messages in quick procession
186 which are updating a zone with inline-signing enabled. This has been
187 fixed. :gl:`#5816` :gl:`!12300`
188
189 - Properly detect private records before copying. ``5c153b85e54``
190
191 We were triggering an assertion when trying to copy a private record
192 to a buffer for modifying. Extend the private type detection and copy
193 the contents after we have rejected invalid private records.
194 :gl:`#5857` :gl:`!12340`
195
196 - Tighten referral DS acceptance. ``ed27fb9524f``
197
198 Named was accepting DS records for sibling zones when it shouldn't
199 have. This has been fixed. :gl:`#5870` :gl:`!12325`
200
201 - Don't synthesize negative responses with pending NSEC. ``86b87dfd290``
202
203 If an NSEC record has not yet been validated and is cached with trust
204 pending, don't use it to synthesize negative responses. :gl:`#5872`
205 :gl:`#5887` :gl:`#5977` :gl:`!12368`
206
207 - Check that an NSEC signer is at or above the name to be validated.
208 ``2afca834141``
209
210 Add a check that an NSEC record being used as a proof of nonexistence
211 for a given name is not signed by a name lower in the DNS hierarchy
212 than the one in question. :gl:`#5876` :gl:`!12324`
213
214 - Don't evict DNSSEC-validated cache data on a CD=1 NXDOMAIN.
215 ``3e6cef2ac66``
216
217 When a client sent a query with the checking-disabled (CD) bit set and
218 the answer was NXDOMAIN, the resolver cached that unvalidated negative
219 response and discarded any DNSSEC-validated records it already held
220 for the same name, even though the validated data was more
221 trustworthy. A single such response - including a forged one - could
222 flush validated records from the cache and force the resolver to fetch
223 them again. The resolver now checks the trust level of the existing
224 data first and leaves the cache unchanged when it is already
225 validated. :gl:`#5877` :gl:`!12344`
226
227 - Fix a 'deny-answer-aliases' configuration bypass issue.
228 ``47d375b9e63``
229
230 It was possible to use a maliciously crafted authoritative zone to
231 make :iscman:`named` resolver synthesize a ``DNAME`` "alias" that
232 should have been rejected by the configured :any:`deny-answer-aliases`
233 option. This has been fixed. :gl:`#5930` :gl:`!12245`
234
235 - Reject external referrals from forwarders. ``cdbc5be8b0c``
236
237 Under `forward-first` policy in a forwarding zone BIND could accept NS
238 above the forward zone apex from negative responses. This has been
239 fixed.
240
241 ISC would like to thank Qifan Zhang, of Palo Alto Networks, for the
242 report. :gl:`#5937` :gl:`!12278`
243
244 - Fix a zone transfer over TLS (XoT) issue when using the opportunistic
245 TLS mode. ``40b64d13862``
246
247 The :iscman:`named` process, running as secondary DNS server,
248 configured to transfer a zone from a primary server using an encrypted
249 XoT transport in opportunistic TLS mode (i.e. without peer
250 certificate/hostname validation) could terminate unexpectedly when the
251 TLS ALPN negotiation with primary server was unsuccessful. This has
252 been fixed. :gl:`#5957` :gl:`!12242`
253
254 - Unvalidated opt-out NSEC3 could be accepted in insecurity proof.
255 ``c3733e12f9e``
256
257 When determining whether an insecure delegation is legitimate, NSEC3
258 opt-out records which had not yet passed validation could be used.
259 This has been fixed. :gl:`#5970` :gl:`!12358`
260
261 - Check wildcard signer and NOQNAME signer match. ``3621c8169bf``
262
263 A positive wildcard answer, and the NSEC3 proof that the requested
264 name doesn't exist in the zone, must both be from the same zone.
265 Otherwise, an NSEC3 from an ancestor zone could be used to interfere
266 with validation.
267
268 We now retrieve the signer name from a wildcard response's signature.
269 An NSEC3 record cannot be used as a NOQNAME proof for the wildcard
270 unless it exactly matches the name one level above the NSEC3.
271 :gl:`#5971` :gl:`!12279`
272
273 - Require secure trust for covering NSEC in the RBT cache.
274 ``b6bfa444e5b``
275
276 The guard against synthesizing negative answers from a pending NSEC
277 (#5977) was only added to the QP cache's find_coveringnsec(); the RBT
278 cache database kept binding any covering NSEC regardless of trust. On
279 builds configured with --with-cachedb=rbt this lets a piggy-backed,
280 unvalidated NSEC drive a synthesized NXDOMAIN, reviving the cache
281 poisoning that was fixed for the default cache.
282
283 query_coveringnsec() only verifies the covering NSEC's trust on its
284 NODATA path; the NXDOMAIN path relies on the database returning a
285 secure record. Require the NSEC and its RRSIG to be dns_trust_secure
286 in find_coveringnsec(), matching the QP cache. :gl:`#5977`
287 :gl:`!12374`
288
289 - Check dns_rdata_fromstruct() return values. ``416b0817d1b``
290
291 In some functions implementing RFC 5011 key maintenance, the results
292 of `dns_rdata_fromstruct()` were not checked. This has been fixed.
293 :gl:`#5982` :gl:`!12183`
294
295 - Fix CNAME resolution failure caused by a cached SERVFAIL response.
296 ``b1e0a58f4f2``
297
298 Under certain circumstances, a cached SERVFAIL response could
299 incorrectly prevent successful resolution of a CNAME target. This
300 could cause resolution failures to persist until the cached SERVFAIL
301 entry expired, even when the CNAME target itself was otherwise
302 resolvable. This issue has been fixed. :gl:`#5983` :gl:`!12259`
303
304 - [CVE-2026-13204] Prevent crash from malformed NSEC/NSEC3 response.
305 ``ad393b09232``
306
307 An assertion could be triggered by an improperly signed NOQNAME proof.
308 This has been fixed.
309
310 ISC thanks Qifan Zhang of Palo Alto Networks for reporting the issue.
311 :gl:`#5985`
312
313 - Reject unsupported RSA DNSKEY shapes during DNSSEC validation.
314 ``ea91570492c``
315
316 An authoritative server publishing an RSA DNSKEY with an unusually
317 large modulus or an exotic public exponent could make each DNSSEC
318 signature check on a validating recursive resolver noticeably more
319 expensive than for a normally sized key. Such DNSKEYs are now treated
320 as invalid. :gl:`#6008` :gl:`!12207`
321
322 - Fix a bug in GeoIP2 string matching. ``f8f5e6a9d77``
323
324 When using GeoIP2 ACLs (see :any:`acl`), :iscman:`named` could
325 incorrectly match a name using a sub-string instead of the full name
326 match. This has been fixed. :gl:`#6019` :gl:`!12235`
327
328 - Fix DNS-over-HTTPS (DoH) quota configuration issue. ``72d538fe269``
329
330 The :any:`http-listener-clients` and
331 :any:`http-streams-per-connection` configuration options could be
332 truncated to smaller values (or to ``0``, which means unlimited) when
333 very big configuration values were used, which exceeded ``65535``. As
334 a note - it is very unlikely that such big values are used in
335 production, and the default values for the affected options are
336 ``300`` and ``100``, correspondingly. This has been fixed. :gl:`#6021`
337 :gl:`!12231`
338
339 - Fix invalid pointer release in JSON statistics-channel response.
340 ``5fe742e3fd1``
341
342 Each response served on a JSON statistics endpoint released the wrong
343 pointer to the JSON library after the response was sent: the response
344 body string instead of the JSON document. With the current responses
345 this does not crash named in practice, but the call is incorrect and
346 can in principle corrupt memory. XML responses are not affected.
347 :gl:`#6024` :gl:`!12274`
348
349 - Truncated reply to a TSIG query no longer stalls the resolver.
350 ``c922cabd46d``
351
352 When an upstream server returned a truncated reply to a query that
353 BIND had signed with TSIG, the resolver could keep waiting for a
354 follow-up UDP packet that never arrived, so the query stalled until it
355 hit resolver-query-timeout and the client received no answer. BIND now
356 treats any reply it cannot authenticate as an immediate failure and
357 returns SERVFAIL right away as a defense in depth. :gl:`#6028`
358 :gl:`!12310`
359
360 - Ignore updates removing DNSKEY RRset with class ANY. ``6a533ec622c``
361
362 When a Dynamic Update is received that removes the ``DNSKEY`` (or
363 ``CDNSKEY``, or ``CDS``) RRset, remove all records except the ones
364 that are in use for signing for the zone. :gl:`#6045` :gl:`!12230`
365
366 - Fix a memory leak when updating a zone with more than 32 DNSSEC keys.
367 ``73440816e41``
368
369 Applying changes to a signed zone via DNS UPDATE or the
370 inline-signing raw-to-secure sync leaked the surplus keys when the
371 zone's key directory held more than 32, slowly growing named's memory
372 use. :gl:`#6051` :gl:`!12332`
373
374 - Fix the memory ordering in the adaptive read-write lock.
375 ``eff9a306d88``
376
377 On hardware with a weak memory model, the internal read-write lock
378 could briefly admit a reader and a writer at the same time, risking
379 sporadic crashes or incorrect data. The reader/writer handshake now
380 uses sequentially consistent ordering so the two can no longer
381 overlap. :gl:`#6060` :gl:`!12205`
382
383 - Print the full OID in PRIVATEOID key comments. ``87397c823dc``
384
385 The OID in the "; alg = ..." comment of a PRIVATEOID key was truncated
386 to sixteen characters. :gl:`#6092` :gl:`!12378`
387
388 - Correct locator decoding for NID, L64, and L32 records.
389 ``8a8cc34a504``
390
391 NID, L64, and L32 records were decoded incorrectly when converted into
392 their parsed structures, because the preference field was not skipped
393 before the locator. :gl:`#6097` :gl:`!12349`
394
395 - Fix a possible crash when cleaning up a view's caches. ``51d7456399d``
396
397 In rare cases named could crash while a view was being removed, for
398 example during reconfiguration or shutdown, as its internal caches
399 were torn down. This has been fixed. :gl:`#6119` :gl:`!12190`
400
401 - Preserve the request message across async SIG(0) processing.
402 ``d6a4aa5ce50``
403
404 For SIG(0)-signed requests, view matching is offloaded and the request
405 is finished asynchronously from ns_client_request_continue(), which
406 passes client->inner.buffer to dns_dt_send(). That buffer aliases the
407 network manager's receive buffer, only valid during the read callback,
408 so it may already be freed and reused, producing garbage dnstap frames
409 (e.g. the "upforwd" sig0-over-DoT test fails with UQ=0).
410
411 Copy the request message when entering async mode and reference the
412 copy, freeing it in ns__client_reset_cb().
413
414 Assisted-by: Claude:claude-opus-4-8 :gl:`#6139` :gl:`!12200`
415
416 - Ignore 0-byte reads in the TCP read callback. ``8588ffec7de``
417
418 Callbacks for libuv stream reads do not signal zero-length reads as a
419 failure signal but rather as EAGAIN/EWOULDBLOCK. This can trigger an
420 assertion when a zero-length read is pushed onto a PROXYv2 endpoint
421 that has not yet processed the headers as it expects a non-NULL region
422 of positive length. :gl:`#6140` :gl:`!12291`
423
424 - Include the IPv6 address's brackets in the parsed URL/URI host.
425 ``9baad48be06``
426
427 The brackets are not included in the host component of the parsed
428 URL/URI. Change the parser to include the brackets. :gl:`#6147`
429 :gl:`!12362`
430
431 - Improve the input validation of the isc_url_parse() function.
432 ``f4c8f08042a``
433
434 The isc_url_parse() function failed to check the input buffer's length
435 and assumed that it can't be bigger than UINT16_MAX, because both the
436 'off' and 'len' fields of the 'isc_url_parser_t' structure are
437 uint16_t.
438
439 Add a check to not accept a buffer longer than 8192 octets.
440 :gl:`#6150` :gl:`!12361`
441
442 - Only print per zone glue stats when query statistics is full.
443 ``097e530348f``
444
445 The code printing query statistics was ignoring the zone-statistics
446 option. This has been fixed. :gl:`#6164` :gl:`!12263`
447
448 - CDS/CDNSKEY records were not removed when re-configuring the server.
449 ``20db02121f7``
450
451 When on an ``rndc reconfig`` the DNSSEC policy changes such that it
452 changes the expected ``CDNSKEY`` and/or ``CDS`` records in the zone,
453 the RRset should be updated accordingly. This did not happen when
454 removing digests from the configuration, or setting `cdnskey no;`.
455 This has been fixed. :gl:`#6166` :gl:`!12284`
456
457 - Fix a crash when querying an empty non-terminal in a wildcard zone in
458 RBTDB. ``b8e5801ec5f``
459
460 A query for an empty non-terminal in a wildcard zone served from the
461 RBT zone database could abort named with an assertion failure. It now
462 returns the correct NODATA answer. :gl:`#6170` :gl:`!12299`
463
464 - Stop reusing outgoing TCP connections the peer has already closed.
465 ``fb0ae8a5d6b``
466
467 ``named`` could hand a new query an idle forwarder/upstream TCP or TLS
468 connection that the peer had already closed, causing the query to fail
469 (and CLOSE-WAIT sockets to pile up). Idle reused connections are now
470 watched, so a close is noticed and the connection is dropped instead
471 of reused. A new ``tcp-reuse-timeout`` option controls how long an
472 idle outgoing connection is kept open for reuse (default 5 seconds).
473 :gl:`#6171` :gl:`!12317`
474
475 - Fix DNSSEC validation failures for names under an apex DNAME.
476 ``cd006ecf235``
477
478 DNSSEC validation could fail with SERVFAIL for names covered by a
479 DNAME at the apex of a signed zone, unless the zone's keys were
480 already validated in the cache. This regression was introduced by the
481 recent fix for resolver stalls on CNAME responses to DS queries.
482 :gl:`#6176` :gl:`!12356`
483
484 - Avoid needless queries when the DNSSEC validation limit is reached.
485 ``45a3e5b8561``
486
487 A validating resolver could send one needless upstream query after
488 reaching its per-fetch DNSSEC validation limit. It now stops
489 immediately.
490
491 - Avoid writing through a const pointer in render_xsl() ``348e5a9ee54``
492
493 render_xsl() served the static XSL stylesheet by casting away the
494 const qualifier of xslmsg and handing the pointer to
495 isc_buffer_reinit():
496
497 p = UNCONST(xslmsg); isc_buffer_reinit(b, p, strlen(xslmsg));
498
499 isc_buffer_reinit() copies any pre-existing buffer content into the
500 new base with memmove(), so the call would write into xslmsg, which is
501 a 'const char[]' living in read-only memory. This is safe today only
502 because the supplied bodybuffer is always freshly initialized with
503 length 0, so the memmove() never runs -- a fragile,
504 action-at-a-distance invariant that GCC's -fanalyzer flags as a write
505 to a const object (-Wanalyzer-write-to-const).
506
507 Use isc_buffer_constinit(), the primitive intended for pointing a
508 buffer at constant data: it goes through isc_buffer_init() and never
509 writes to the base. This drops the UNCONST cast, keeps xslmsg in
510 read-only memory, and silences the analyzer warning.
511
512 Assisted-by: Claude:claude-opus-4-8 :gl:`!12309`
513
514 - Don't serve a stale CNAME or record when fresh data of the other
515 exists. ``1cf6838c271``
516
517 When a cached name held both a CNAME and records of another type one
518 stale, the other still fresh named with serve-stale could return the
519 expired set instead of the fresh one, in either direction. It now
520 prefers whichever is fresh. :gl:`!12305`
521
522 - Fix compatibility with OpenSSL 1.0.2u. ``11fcd8206ab``
523
524 BIND failed to build with OpenSSL 1.0.2u. Add the missing header file
525 includes. :gl:`!11897`
526
527 - Only update the global tid_count once. ``746d9bfd3a8``
528
529 Skip updating the `tid_count` value on repeated calls to prevent
530 ThreadSanitizer 'data race'. :gl:`!12188`
531
532
533