
مدقق ثابت يعمل دون اتصال يفحص ملفات Java jars المعبأة بحثًا عن إصدارات netty-resolver-dns الضعيفة ويكتشف ما إذا كان Spring WebClient يستخدم فعليًا محلل DNS الخاص بـ Netty.
أداة فحص دون اتصال لثلاث ثغرات تسميم ذاكرة DNS المؤقتة في io.netty:netty-resolver-dns —
CVE-2026-45674 وCVE-2026-47691 وCVE-2026-45673 — وللسؤال الذي لا يستطيع رقم
الإصدار الإجابة عليه: هل يستخدم تطبيقك هذا المُحلِّل فعلاً؟
إذا كنت تستخدم Spring WebClient، فالإجابة على الأرجح نعم، حتى وإن لم يظهر
netty-resolver-dns في pom.xml الخاص بك ولم يستدعه أي شيء في شفرتك.
java -jar netty-resolver-dns-check-0.1.0.jar path/to/your-app.jar
يصل netty-resolver-dns عبر أربعة مستويات:
spring-boot-starter-webflux
└ spring-boot-starter-reactor-netty
└ reactor-netty-http
└ reactor-netty-core
└ netty-resolver-dns (كل رابط: compile scope)
وهو ليس موجوداً على مسار الفئات (classpath) فحسب. بل إن HttpClient الخاص بـ Reactor Netty — وهو
الموصل الذي يختاره Spring Boot لـ WebClient كلما كان Reactor Netty موجوداً — يحل أسماء المضيفين
باستخدام DnsAddressResolverGroup الخاص بـ Netty، وليس مُحلِّل JDK:
HttpClientConfig.defaultAddressResolverGroup() → HttpResources.getOrCreateDefaultResolver()TcpResources.getOrCreateDefaultResolver() → NameResolverProvider.newNameResolverGroup(...)NameResolverProvider.newNameResolverGroup → new DnsNameResolverBuilder() → new DnsAddressResolverGroup(builder)(الأمر ذاته في reactor-netty 1.1.x و1.2.x و1.3.x وmain.) ترتيب اكتشاف الموصل في Spring Boot هو
reactor > jetty > httpComponents > jdk، لذا يفوز Reactor Netty كلما كان موجوداً.
لم نتوقف عند قراءة الشفرة المصدرية. في التجربة المضبوطة أدناه، أرسل تطبيق Spring Boot 3.5.14
افتراضي يقوم بطلب WebClient واحد استعلام DNS حقيقياً واحداً عبر مُحلِّل Netty
(WRITE: UDP ... DefaultDnsQuestion(example.com.)).
تقول التنبيهات الخاصة بـ CVE-2026-45674 وCVE-2026-47691 بصراحة: "أي تطبيق يستخدم مُحلِّل DNS الخاص بـ Netty يتأثر."
تشترك الثغرات الثلاث في الإصلاح ذاته: 4.1.135.Final (خط 4.1) / 4.2.15.Final (خط 4.2).
مقروءة من كل spring-boot-dependencies-<v>.pom (<netty.version>)، بتاريخ 2026-09-11:
الإصدارات المُصلَّحة كلها على Maven Central. الترقية تعمل؛ وهذه الأداة لا تدّعي خلاف ذلك.
رقم الإصدار هو سطر واحد من mvn dependency:tree. السؤال الأصعب هو ما إذا كان المُحلِّل
قيد الاستخدام فعلاً. لذا بنينا أربعة ملفات fat jar حقيقية لـ Spring Boot 3.5.14 وواحداً على 3.5.16،
وقسنا الحقيقة الفعلية — استعلامات DNS التي أرسلها Netty فعلاً — مقابل ما تستنتجه هذه الأداة
من الـ jar وحده:
النتيجة الصادقة: تقول الأداة بموثوقية "قيد الاستخدام" عندما لا يوجد تجاوز، وتجد آثار التجاوز في شفرتك وإعداداتك (3 من 3، دون إيجابية كاذبة على A). لكنها لا تستطيع التمييز بين B (كل شيء متجاوَز) وD (عميل واحد لا يزال على الافتراضي) — فدليل البايت كود لديهما متطابق. لذا فإن وجود تجاوز لا يجعلها تقول "غير متأثر" أبداً؛ بل تقول "افحص يدوياً"، وتقدم لك الفحص الذي يستغرق دقيقة أدناه.
--logging.level.io.netty.resolver.dns=DEBUGWRITE: UDP في السجل — موجود: مُحلِّل Netty قيد الاستخدام؛ غائب: ذلك الطلب لم يستخدمهلا تحكم بناءً على "هل تم تحميل DnsNameResolver؟". التطبيق B استبدل المُحلِّل ومع ذلك حمّل
تلك الفئة، لأن مجموعة المُحلِّل الافتراضية تُبنى بحماس. أسطر الاستعلام وحدها هي الدليل.
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
تقرأ ما هو مُحزَّم فعلاً (fat jar BOOT-INF/lib، war WEB-INF/lib، jars متداخلة)،
وليس pom.xml — فالاعتمادية انتقالية، لذا سيخبرك الـ pom بأنه غير موجود.
يُحدَّد الوجود بواسطة الفئة io/netty/resolver/dns/DnsNameResolver.class، وليس بواسطة
بيانات الإصدار. تُبحث آثار التجاوز فقط في فئاتك الخاصة وapplication*.properties/yml
(فمكتبات jar تشير إلى هذه الفئات بنفسها).
المخرجات بالصينية؛ أسطر الحكم ومعرّفات CVE هي ما يجب أن تعتمد عليه السكربتات.
HttpClient الخاص بـ Reactor Netty مباشرة (مثل بوابة) لا
تُحلَّل بشكل منفصل — إذا كان Reactor Netty موجوداً، يُفترض المسار الافتراضي.واجهة GitHub advisory API، مقروءة بتاريخ 2026-09-11:
جدول Spring Boot موجود في BootTable.java؛ ويعيد اختبار وحدة اشتقاق العبارات الثلاث في
القسم 2 منه، لذا لا يمكن للجدول والادعاءات أن ينفصلا بصمت.
يحتوي evidence/ على التطبيقات الخمسة (A–E) وruntime.sh، الذي يعدّ أسطر WRITE: UDP لكل تطبيق.
يشغّل tools/e2e_real_jars.py هذه الأداة مقابل الملفات الخمسة ذاتها ويؤكد كل حكم.
بناء التطبيقات يتطلب Maven 3.6.3 أو أحدث.
| الرمز | المعنى |
|---|---|
| 0 | لا تنطبق أي من الثغرات الثلاث (إصدار مُصلَّح) |
| 1 | وُجد إصدار متأثر — بما في ذلك عند العثور على آثار تجاوز |
| 2 | لا يمكن الحكم (لم يُعثر على netty-resolver-dns، إصدار غير معروف، وسائط خاطئة) |
Apache License 2.0
| Spring Boot | netty الافتراضي |
|---|
| 3.4.0 – 3.4.13 | 4.1.115 – 4.1.130 | متأثر — لا يوجد إصدار 3.4.x يتضمن الإصلاح |
| 3.5.0 – 3.5.14 | 4.1.121 – 4.1.132 | متأثر |
| 3.5.15 + | 4.1.135 | مُصلَّح |
| 4.0.0 – 4.0.6 | 4.2.7 – 4.2.12 | متأثر |
| 4.0.7 + | 4.2.15 + | مُصلَّح |
| التطبيق | ما يفعله | استعلامات Netty DNS (وقت التشغيل) | هذه الأداة (ساكن) |
|---|
| A | WebClient.builder() الافتراضي | 1 | قيد الاستخدام |
| B | .resolver(DefaultAddressResolverGroup.INSTANCE) | 0 | وُجد تجاوز → افحص يدوياً |
| C | spring.http.reactiveclient.connector=jdk | 0 | وُجد تجاوز → افحص يدوياً |
| D | اثنان WebClient، واحد فقط متجاوَز | 1 | وُجد تجاوز → افحص يدوياً |
| E | افتراضي، Spring Boot 3.5.16 | 1 (على 4.1.135 المُصلَّح) | غير متأثر |
| CVE | GHSA | الخطورة | متأثر → مُصلَّح |
|---|
| CVE-2026-45674 | GHSA-676x-f7gg-47vc | عالية 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 | عالية 8.7 | نفسه |
| CVE-2026-45673 | GHSA-xmv7-r254-6q78 | متوسطة 6.8 | نفسه |
| 4 | تعذّرت قراءة بعض الملفات — "لم أستطع قراءته" يجب ألا تبدو أبداً كنجاح |