
Offline-Statikprüfer, der gepackte Java-JARs auf anfällige Versionen von netty-resolver-dns untersucht und erkennt, ob Spring WebClient tatsächlich den DNS-Resolver von Netty verwendet.
Offline-Prüfwerkzeug für drei DNS-Cache-Poisoning-CVEs in io.netty:netty-resolver-dns —
CVE-2026-45674, CVE-2026-47691 und CVE-2026-45673 — und für die Frage, die die
Versionsnummer nicht beantworten kann: verwendet Ihre Anwendung diesen Resolver tatsächlich?
Wenn Sie Spring WebClient verwenden, ist die Antwort sehr wahrscheinlich ja, obwohl
netty-resolver-dns nirgends in Ihrer pom.xml steht und nichts in Ihrem Code es aufruft.
java -jar netty-resolver-dns-check-0.1.0.jar path/to/your-app.jar
netty-resolver-dns kommt vier Ebenen tief:
spring-boot-starter-webflux
└ spring-boot-starter-reactor-netty
└ reactor-netty-http
└ reactor-netty-core
└ netty-resolver-dns (jede Verbindung: compile scope)
Und es ist nicht nur im Classpath. Reactor Netty's HttpClient — der Connector, den Spring Boot
für WebClient wählt, wann immer Reactor Netty vorhanden ist — löst Hostnamen mit Netty's eigenem
DnsAddressResolverGroup auf, nicht mit dem JDK-Resolver:
HttpClientConfig.defaultAddressResolverGroup() → HttpResources.getOrCreateDefaultResolver()TcpResources.getOrCreateDefaultResolver() → NameResolverProvider.newNameResolverGroup(...)NameResolverProvider.newNameResolverGroup → new DnsNameResolverBuilder() → new DnsAddressResolverGroup(builder)(Gleiches in reactor-netty 1.1.x, 1.2.x, 1.3.x und main.) Die Connector-Erkennungsreihenfolge von Spring Boot ist
reactor > jetty > httpComponents > jdk, also gewinnt Reactor Netty, wann immer es vorhanden ist.
Wir haben nicht beim Lesen des Quellcodes haltgemacht. Im unten beschriebenen kontrollierten Experiment
sendete eine Standard-Spring-Boot-3.5.14-App, die eine einzige WebClient-Anfrage stellte, eine echte DNS-Abfrage über Netty's Resolver
(WRITE: UDP ... DefaultDnsQuestion(example.com.)).
Die Advisories für CVE-2026-45674 und CVE-2026-47691 sagen es unverblümt: "Jede Anwendung, die Netty's DNS-Resolver verwendet, ist betroffen."
Alle drei CVEs teilen denselben Fix: 4.1.135.Final (4.1-Zweig) / 4.2.15.Final (4.2-Zweig).
Gelesen aus jeder spring-boot-dependencies-<v>.pom (<netty.version>), 2026-09-11:
| Spring Boot | Standard-Netty | |
|---|---|---|
| 3.4.0 – 3.4.13 | 4.1.115 – 4.1.130 | betroffen — kein 3.4.x-Release liefert den Fix aus |
| 3.5.0 – 3.5.14 | 4.1.121 – 4.1.132 | betroffen |
| 3.5.15 + | 4.1.135 | behoben |
| 4.0.0 – 4.0.6 | 4.2.7 – 4.2.12 | betroffen |
| 4.0.7 + | 4.2.15 + | behoben |
Die behobenen Versionen sind alle auf Maven Central. Ein Upgrade funktioniert; dieses Werkzeug behauptet nichts anderes.
Eine Versionsnummer ist eine Zeile aus mvn dependency:tree. Die schwierigere Frage ist, ob der
Resolver wirklich verwendet wird. Also haben wir vier echte Spring-Boot-3.5.14-Fat-Jars gebaut und eines auf 3.5.16,
und die Ground Truth gemessen — DNS-Abfragen, die tatsächlich von Netty gesendet werden — gegen das, was dieses Werkzeug
allein aus dem Jar ableitet:
| App | Was sie tut | Netty-DNS-Abfragen (Laufzeit) | Dieses Werkzeug (statisch) |
|---|---|---|---|
| A | Standard WebClient.builder() | 1 | in Verwendung |
| B | .resolver(DefaultAddressResolverGroup.INSTANCE) | 0 | Override gefunden → manuell prüfen |
| C | spring.http.reactiveclient.connector=jdk | 0 | Override gefunden → manuell prüfen |
| D | zwei WebClients, nur einer überschrieben | 1 | Override gefunden → manuell prüfen |
| E | Standard, Spring Boot 3.5.16 | 1 (auf dem behobenen 4.1.135) | nicht betroffen |
Das ehrliche Ergebnis: Das Werkzeug sagt zuverlässig "in Verwendung", wenn kein Override vorhanden ist, und es findet Override-Spuren in Ihrem Code und Ihrer Konfiguration (3 von 3, kein Fehlalarm bei A). Es kann B (alles überschrieben) nicht von D (ein Client noch auf dem Standard) unterscheiden — ihre Bytecode-Evidenz ist identisch. Ein Override führt also nie dazu, dass es "nicht betroffen" sagt; es sagt "manuell prüfen" und gibt Ihnen die Ein-Minuten-Prüfung unten.
--logging.level.io.netty.resolver.dns=DEBUGWRITE: UDP im Log — vorhanden: Netty's Resolver wird verwendet; nicht vorhanden: diese Anfrage hat ihn nicht verwendetUrteilen Sie nicht danach, ob "wurde DnsNameResolver geladen?". App B ersetzte den Resolver und lud
diese Klasse trotzdem, weil die Standard-Resolver-Gruppe eifrig aufgebaut wird. Nur die Abfragezeilen sind Beweis.
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
Es liest, was tatsächlich gepackt ist (Fat-Jar BOOT-INF/lib, War WEB-INF/lib, verschachtelte Jars),
nicht pom.xml — die Abhängigkeit ist transitiv, die Pom würde Ihnen also sagen, dass sie nicht da ist.
Das Vorhandensein wird durch die Klasse io/netty/resolver/dns/DnsNameResolver.class entschieden, nicht durch Versions-
Manifeste. Override-Spuren werden nur in Ihren eigenen Klassen und application*.properties/yml gesucht
(Bibliotheks-Jars referenzieren diese Klassen selbst).
Die Ausgabe ist auf Chinesisch; die Verdict-Zeilen und CVE-IDs sind das, worauf Skripte sich stützen sollten.
HttpClient direkt verwenden (zum Beispiel ein Gateway), werden nicht
separat analysiert — wenn Reactor Netty vorhanden ist, wird der Standardpfad angenommen.GitHub-Advisory-API, gelesen 2026-09-11:
| CVE | GHSA | Schweregrad | Betroffen → behoben |
|---|---|---|---|
| CVE-2026-45674 | GHSA-676x-f7gg-47vc | hoch 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 | hoch 8.7 | gleich |
| CVE-2026-45673 | GHSA-xmv7-r254-6q78 | medium 6.8 | gleich |
Die Spring-Boot-Tabelle steht in BootTable.java; ein Unit-Test leitet die drei Aussagen in
Abschnitt 2 daraus erneut ab, sodass Tabelle und Behauptungen nicht stillschweigend auseinanderdriften können.
evidence/ enthält die fünf Apps (A–E) und runtime.sh, das WRITE: UDP-Zeilen pro App zählt.
tools/e2e_real_jars.py führt dieses Werkzeug gegen dieselben fünf Jars aus und prüft jedes Verdict.
Das Bauen der Apps erfordert Maven 3.6.3 oder neuer.
| Code | Bedeutung |
|---|---|
| 0 | keine der drei CVEs trifft zu (behobene Version) |
| 1 | betroffene Version gefunden — auch wenn Override-Spuren gefunden wurden |
| 2 | kann nicht beurteilen (kein netty-resolver-dns gefunden, unbekannte Version, ungültige Argumente) |
| 4 | eine Datei konnte nicht gelesen werden — "Ich konnte es nicht lesen" darf nie wie ein Bestehen aussehen |
Apache License 2.0