---
id: RUSTSEC-2026-0118
aliases:
  - GHSA-3v94-mw7p-v465
  - RUSTSEC-2026-0120
title: >-
  NSEC3 closest-encloser proof validation enters unbounded loop on cross-zone
  responses
summary: >-
  NSEC3 closest-encloser proof validation enters unbounded loop on cross-zone
  responses
severity: none
vendor: hickory-proto
product: hickory-proto
ecosystem: rust
affected:
  - 'hickory-proto >= 0.25.0-alpha.3, < 0.26.0-beta.1'
patched:
  - hickory-proto 0.26.0-beta.1
published: '2026-05-01'
updated: '2026-10-12'
sourceUpdated: '2026-10-12T18:00:13.245565018Z'
source: OSV
sourceUrl: 'https://osv.dev/vulnerability/RUSTSEC-2026-0118'
references:
  - url: 'https://crates.io/crates/hickory-proto'
  - url: 'https://rustsec.org/advisories/RUSTSEC-2026-0118.html'
  - url: 'https://github.com/hickory-dns/hickory-dns/pull/3597'
tags:
  - osv
  - rust
ingestedAt: '2026-10-13T11:45:30.191Z'
---

## Overview

The NSEC3 closest-encloser proof validation in `hickory-proto`'s
`DnssecDnsHandle` walks from the QNAME up to the SOA owner name, building a
list of candidate encloser names. The iterator used assumes the
QNAME is a descendant of the SOA owner, terminating only when the current
candidate equals the SOA name. When the SOA in a response's authority section
is not an ancestor of the QNAME, the loop stalls at the DNS root and never
terminates, repeatedly calling `Name::base_name()` and pushing newly allocated
`Name` and hashed-name entries into the candidate `Vec`.

The bug is reachable by any caller of `DnssecDnsHandle` — including the
resolver, recursor, and client — when built with the `dnssec-ring` or
`dnssec-aws-lc-rs` feature and configured to perform DNSSEC validation. It is
triggered while validating a NoData or NXDomain response whose authority
section contains an SOA record from a zone other than an ancestor of the
QNAME, on a code path that requires NSEC3 closest-encloser proof. In practice
this can be reached through an insecure CNAME chain that crosses zone
boundaries into a DNSSEC-signed zone returning NoData, but the minimum
condition is just a mismatched SOA owner on a response requiring NSEC3
validation.

A `debug_assert_ne!(name, Name::root())` guards the loop body, so debug builds
abort with a panic on the first iteration past the root. Release builds
compile the assertion out and run the loop unbounded, allocating until the
process exhausts available memory (OOM). A reachable upstream attacker who
can return such a response can therefore crash a debug-built validator or
exhaust memory on a release-built one.

The affected code was migrated from `hickory-proto` to `hickory-net` as part of
the 0.26.0 release. The `hickory-proto` 0.26.x release no longer offers
`DnssecDnsHandle` and so we recommend all affected users update to `hickory-net`
0.26.1 when the implementation of that type is required.

## Affected packages

- `hickory-proto >= 0.25.0-alpha.3, < 0.26.0-beta.1`

## Remediation

Upgrade to a patched release:

- `hickory-proto 0.26.0-beta.1`
