
Checker statico offline che ispeziona i jar Java pacchettizzati per individuare versioni vulnerabili di netty-resolver-dns e rileva se Spring WebClient utilizza effettivamente il resolver DNS di Netty.
Checker offline per tre CVE di DNS cache poisoning in io.netty:netty-resolver-dns —
CVE-2026-45674, CVE-2026-47691 e CVE-2026-45673 — e per la domanda a cui il
numero di versione non può rispondere: la tua applicazione sta effettivamente usando quel resolver?
Se usi Spring WebClient, la risposta è molto probabilmente sì, anche se
netty-resolver-dns non è da nessuna parte nel tuo pom.xml e nulla nel tuo codice lo chiama.
java -jar netty-resolver-dns-check-0.1.0.jar path/to/your-app.jar
netty-resolver-dns arriva a quattro livelli di profondità:
spring-boot-starter-webflux
└ spring-boot-starter-reactor-netty
└ reactor-netty-http
└ reactor-netty-core
└ netty-resolver-dns (ogni collegamento: scope compile)
E non è solo sul classpath. L'HttpClient di Reactor Netty — il connettore che Spring Boot
sceglie per WebClient ogni volta che Reactor Netty è presente — risolve i nomi host con il
DnsAddressResolverGroup di Netty, non con il resolver della JDK:
HttpClientConfig.defaultAddressResolverGroup() → HttpResources.getOrCreateDefaultResolver()TcpResources.getOrCreateDefaultResolver() → NameResolverProvider.newNameResolverGroup(...)NameResolverProvider.newNameResolverGroup → new DnsNameResolverBuilder() → new DnsAddressResolverGroup(builder)(Lo stesso in reactor-netty 1.1.x, 1.2.x, 1.3.x e main.) L'ordine di rilevamento dei connettori di Spring Boot è
reactor > jetty > httpComponents > jdk, quindi Reactor Netty vince ogni volta che è presente.
Non ci siamo fermati alla lettura del codice sorgente. Nell'esperimento controllato di seguito, un'app Spring Boot 3.5.14
predefinita che effettua una richiesta WebClient ha inviato una vera query DNS attraverso il resolver di Netty
(WRITE: UDP ... DefaultDnsQuestion(example.com.)).
Gli advisory per CVE-2026-45674 e CVE-2026-47691 lo dicono chiaramente: "Qualsiasi applicazione che utilizza il resolver DNS di Netty è interessata."
Tutte e tre le CVE condividono la stessa correzione: 4.1.135.Final (linea 4.1) / 4.2.15.Final (linea 4.2).
Letto da ciascun spring-boot-dependencies-<v>.pom (<netty.version>), 2026-09-11:
| Spring Boot | netty predefinito | |
|---|---|---|
| 3.4.0 – 3.4.13 | 4.1.115 – 4.1.130 | interessato — nessuna release 3.4.x include la correzione |
| 3.5.0 – 3.5.14 | 4.1.121 – 4.1.132 | interessato |
| 3.5.15 + | 4.1.135 | corretto |
| 4.0.0 – 4.0.6 | 4.2.7 – 4.2.12 | interessato |
| 4.0.7 + | 4.2.15 + | corretto |
Le versioni corrette sono tutte su Maven Central. L'aggiornamento funziona; questo strumento non afferma il contrario.
Un numero di versione è una riga di mvn dependency:tree. La domanda più difficile è se il
resolver è realmente in uso. Così abbiamo creato quattro veri fat jar Spring Boot 3.5.14 e uno su 3.5.16,
e misurato la verità effettiva — le query DNS realmente inviate da Netty — rispetto a ciò che questo strumento
deduce dal solo jar:
| App | Cosa fa | Query DNS Netty (runtime) | Questo strumento (statico) |
|---|---|---|---|
| A | WebClient.builder() predefinito | 1 | in uso |
| B | .resolver(DefaultAddressResolverGroup.INSTANCE) | 0 | override trovato → verificare manualmente |
| C | spring.http.reactiveclient.connector=jdk | 0 | override trovato → verificare manualmente |
| D | due WebClient, solo uno sovrascritto | 1 | override trovato → verificare manualmente |
| E | predefinito, Spring Boot 3.5.16 | 1 (sul 4.1.135 corretto) | non interessato |
Il risultato onesto: lo strumento dice in modo affidabile "in uso" quando non c'è override, e trova tracce di override nel tuo codice e nella configurazione (3 su 3, nessun falso positivo su A). Non può distinguere B (tutto sovrascritto) da D (un client ancora sul default) — la loro evidenza nel bytecode è identica. Quindi un override non lo fa mai dire "non interessato"; dice "verificare manualmente", e ti dà il controllo di un minuto qui sotto.
--logging.level.io.netty.resolver.dns=DEBUGWRITE: UDP nel log — presente: il resolver di Netty è in uso; assente: quella richiesta non lo ha usatoNon giudicare da "è stato caricato DnsNameResolver?". L'app B ha sostituito il resolver e ha comunque caricato
quella classe, perché il resolver group predefinito viene costruito in modo eager. Solo le righe delle query sono prova.
java -jar netty-resolver-dns-check-0.1.0.jar <directory | jar | war>
java -jar netty-resolver-dns-check-0.1.0.jar --version-of 4.1.132.Final
Legge ciò che è effettivamente pacchettizzato (fat jar BOOT-INF/lib, war WEB-INF/lib, jar annidati),
non pom.xml — la dipendenza è transitiva, quindi il pom ti direbbe che non c'è.
La presenza è decisa dalla classe io/netty/resolver/dns/DnsNameResolver.class, non dai manifest
di versione. Le tracce di override vengono cercate solo nelle tue classi e in application*.properties/yml
(i jar delle librerie fanno riferimento a queste classi stesse).
L'output è in cinese; le righe di verdetto e gli id CVE sono ciò su cui gli script dovrebbero basarsi.
HttpClient di Reactor Netty (per esempio un gateway) non sono
analizzate separatamente — se Reactor Netty è presente, si presume il percorso predefinito.GitHub advisory API, letto 2026-09-11:
| CVE | GHSA | Gravità | Interessato → corretto |
|---|---|---|---|
| CVE-2026-45674 | GHSA-676x-f7gg-47vc | high 8.7 | <= 4.1.134.Final → 4.1.135.Final · 4.2.0–4.2.14 → 4.2.15.Final |
| CVE-2026-47691 | GHSA-5pvg-856g-cp85 | high 8.7 | stesso |
| CVE-2026-45673 | GHSA-xmv7-r254-6q78 | medium 6.8 | stesso |
La tabella di Spring Boot è in BootTable.java; un unit test ri-deriva le tre affermazioni della
sezione 2 da essa, così la tabella e le affermazioni non possono divergere silenziosamente.
evidence/ contiene le cinque app (A–E) e runtime.sh, che conta le righe WRITE: UDP per app.
tools/e2e_real_jars.py esegue questo strumento sugli stessi cinque jar e verifica ogni verdetto.
La compilazione delle app richiede Maven 3.6.3 o successivo.
| Codice | Significato |
|---|---|
| 0 | nessuna delle tre CVE si applica (versione corretta) |
| 1 | trovata versione interessata — incluso quando sono state trovate tracce di override |
| 2 | impossibile giudicare (nessun netty-resolver-dns trovato, versione sconosciuta, argomenti errati) |
| 4 | alcuni file non sono stati leggibili — "non sono riuscito a leggerlo" non deve mai sembrare un superamento |
Apache License 2.0