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