VYPR
Medium severity6.2NVD Advisory· Published Apr 7, 2026· Updated Apr 16, 2026

CVE-2026-35406

CVE-2026-35406

Description

Aardvark-dns is an authoritative dns server for A/AAAA container records. From 1.16.0 to 1.17.0, a truncated TCP DNS query followed by a connection reset causes aardvark-dns to enter an unrecoverable infinite error loop at 100% CPU. This vulnerability is fixed in 1.17.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
netavarkcrates.io
>= 1.16.0, < 1.17.11.17.1

Affected products

1

Patches

1
3b49ea7b38bd

fix handling of incorrect tcp packets

https://github.com/containers/aardvark-dnsPaul HolzingerApr 2, 2026via ghsa
2 files changed · +46 15
  • src/dns/coredns.rs+20 15 modified
    @@ -17,7 +17,6 @@ use hickory_proto::{
         DnsStreamHandle,
     };
     use log::{debug, error, trace, warn};
    -use std::io::Error;
     use std::net::{IpAddr, SocketAddr};
     use std::sync::Arc;
     use std::sync::Mutex;
    @@ -83,15 +82,21 @@ impl CoreDns {
                         break;
                     },
                     v = receiver.next() => {
    -                    let msg_received = match v {
    -                        Some(value) => value,
    +                    let msg = match v {
    +                        Some(value) => match value {
    +                            Ok(msg) => msg,
    +                            Err(e) => {
    +                                debug!("Error parsing dns message {e:?}");
    +                                continue;
    +                            },
    +                        },
                             None => {
                                 // None received, nothing to process so continue
                                 debug!("None recevied from stream, continue the loop");
                                 continue;
                             }
                         };
    -                    Self::process_message(&self.inner, msg_received, &sender_original, Protocol::Udp).await;
    +                    Self::process_message(&self.inner, msg, &sender_original, Protocol::Udp).await;
                     },
                     res = tcp_listener.accept() => {
                         match res {
    @@ -122,9 +127,16 @@ impl CoreDns {
                 // we do not want this so add a 3s timeout then we close the socket.
                 match tokio::time::timeout(Duration::from_secs(3), hickory_stream.next()).await {
                     Ok(message) => match message {
    -                    Some(msg) => {
    -                        Self::process_message(&data, msg, &sender_original, Protocol::Tcp).await
    -                    }
    +                    Some(msg_result) => match msg_result {
    +                        Ok(msg) => {
    +                            Self::process_message(&data, msg, &sender_original, Protocol::Tcp).await
    +                        }
    +                        Err(e) => {
    +                            debug!("Error parsing dns message {e:?}");
    +                            // error on that stream, abort so we do not try reusing this one for more messages.
    +                            break;
    +                        }
    +                    },
                         // end of stream
                         None => break,
                     },
    @@ -140,17 +152,10 @@ impl CoreDns {
     
         async fn process_message(
             data: &CoreDnsData,
    -        msg_received: Result<SerialMessage, Error>,
    +        msg: SerialMessage,
             sender_original: &BufDnsStreamHandle,
             proto: Protocol,
         ) {
    -        let msg = match msg_received {
    -            Ok(msg) => msg,
    -            Err(e) => {
    -                error!("Error parsing dns message {e:?}");
    -                return;
    -            }
    -        };
             let backend = data.backend.load();
             let src_address = msg.addr();
             let mut sender = sender_original.with_remote_addr(src_address);
    
  • test/100-basic-name-resolution.bats+26 0 modified
    @@ -371,3 +371,29 @@ function teardown() {
     	run_in_container_netns "$a1_pid" "dig" "+short" "second-server.test" "@$gw"
     	assert "$output" == "192.168.100.2" "should resolve using second DNS server after resolv.conf change"
     }
    +
    +@test "check for incorrect tcp packet" {
    +	setup_dnsmasq
    +
    +	subnet_a=$(random_subnet 5)
    +	create_config network_name="podman1" container_id=$(random_string 64) container_name="aone" subnet="$subnet_a"
    +	config_a1=$config
    +	ip_a1=$(echo "$config_a1" | jq -r .networks.podman1.static_ips[0])
    +	gw=$(echo "$config_a1" | jq -r .network_info.podman1.subnets[0].gateway)
    +	create_container "$config_a1"
    +	a1_pid=$CONTAINER_NS_PID
    +
    +	# send custom crafted package, first two bytes mean package length 60 but we never send more and close instead
    +	run_in_container_netns "$a1_pid" socat - TCP4:$gw:53 <<<$'\x00\x3c'
    +
    +	# wait a second to meaningful check cpu usage
    +	sleep 1
    +
    +	av_cpu=$(ps -o c --no-headers -p $(<$AARDVARK_TMPDIR/aardvark-dns/aardvark.pid))
    +	echo $av_cpu --
    +	assert "$av_cpu" -lt 5 "aardvark-dns used to much cpu"
    +
    +	# ensure dns via tcp still works
    +	run_in_container_netns "$a1_pid" "dig" +tcp "+short" "aone" "@$gw"
    +	assert "$ip_a1"
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.