ما الذي حدث، مع التواريخ
في 17 أكتوبر 2026 أبلغ باحث برامج الجذور بأن ثماني سلطات وسيطة تابعة لـ eMudhra أُنشئت بمفاتيح مولَّدة بشكل سيئ. حظر Firefox وChrome هذه الشهادات في اليوم نفسه. وفي 20 أكتوبر 2026 بدأت Microsoft بحظرها، وانتقلت حزمة curl إلى نسخة 20 أكتوبر. وفي 22 أكتوبر 2026 لحقت Apple بذلك للتطبيقات التي تستخدم أطرها الشبكية.
وفي 20 أكتوبر 2026 نشرت Debian أيضاً النشرة DSA-6572-1: الحزمة ca-certificates بالإصدار 20250419+deb13u1، لنسخة Debian المستقرة (trixie)، تزيل الشهادتين المسميتين «emSign ECC Root CA - G3» و«Comodo AAA Services root». وهناك ملاحظتان مهمتان لاحقاً. تتحدث النشرة عن وسيطات eMudhra المخترقة، لكن الشهادتين اللتين تذكرهما تحملان أسماء جذور. كما أنها لا تذكر إصداراً مصححاً إلا لـ trixie: أما التوزيعات الأخرى فاقرأ نشرة كل توزيعة بدل الافتراض.
لماذا لا يغلق «المتصفحات حظرت» الملف
هذا هو الاعتراض الأكثر شيوعاً، وهو صحيح في نصفه. فبحسب صفحة المرجع التي نشرها الباحث، لم يكن ممكناً مهاجمة المتصفحات التي تفرض شفافية الشهادات (Certificate Transparency) عبر هذه الوسيطات. لكن الخادم الذي يستدعي واجهة برمجية، وسكربت النشر الذي يستنسخ مستودعاً، والمهمة المجدولة التي تنزل أرشيفاً، والحاوية التي تثبت اعتمادية، ليست متصفحات. هذه العملاء تتحقق من السلسلة مقابل ملف، وفي الغالب لا تتحقق من الشفافية ولا من الإبطال. ففي 28 أكتوبر 2026 أشارت صفحة المرجع مثلاً إلى أن أدوات سطر الأوامر من Apple (git وcurl وpython3) كانت ما تزال تثق بهذه الشهادات.
الاعتراض الثاني: من المسؤول؟ الوكالة تحتفظ بعلاقتها مع العميل. أما البنية التحتية فتُفحص خادماً بعد خادم، ولن يقوم بذلك أحد غيرك.
أين يوجد مخزن الثقة في الجهاز
- حزمة النظام —
ca-certificatesعلى Debian وUbuntu وAlpine، وبالاسم نفسه على RHEL ومشتقاتها. وهي المرجع لكل ما يقرأ/etc/ssl/certs. - حزمة curl — بحسب طريقة البناء يقرأ curl مخزن النظام أو ملفاً مستقلاً. والأمر
curl-config --caيبين أيهما. - Python وcertifi — تضم الوحدة
certifiحزمتها الخاصة ويستعملها pip. وتحديث النظام لا يمسها. - Node.js — يضم الملف التنفيذي قائمة سلطات. و
NODE_EXTRA_CA_CERTSتضيف سلطات ولا تحذف أي واحدة. - Java — ملف
cacertsفي JDK مخزن مستقل عن البقية. وكان تصحيح OpenJDK ما يزال معلقاً في صفحة المرجع، ولا شيء يضمن أن توزيعتك تنقل إليه تحديث حزمة النظام. - كل صورة حاوية — لها
/etc/ssl/certsالخاص بها، مجمّد وقت البناء. ولا يصلها تصحيح المضيف.
متطلبات الفحص بالأرقام
احسب وصول root أو sudo على كل جهاز، ونحو 15 دقيقة للمرور الأول على الخادم، ثم 5 دقائق كروتين حين تحفظ الأوامر. هناك خمسة مواضع للفحص في كل جهاز (حزمة النظام وcurl وcertifi وNode وJava) وموضع إضافي لكل صورة حاوية. أبقِ في متناولك مضيفَي اختبار على الأقل تعرف سلسلتهما، مثل www.your-domain.com وواجهة برمجية تستدعيها تطبيقاتك. وبالنسبة لخدمات Java خطط أيضاً لنافذة إعادة تشغيل: فالمخزن المستبدل لا يُقرأ من جديد إلا عند إقلاع JVM.
الإجراء، خادماً بعد خادم
قراءة إصدار الحزمة
dpkg -l ca-certificatesعلى Debian وUbuntu، وrpm -q ca-certificatesعلى RHEL ومشتقاتها، وapk info -v ca-certificatesعلى Alpine. وعلى Debian المستقرة (trixie) الإصدار المصحح في النشرة DSA-6572-1 هو 20250419+deb13u1: فإن كان إصدارك أقدم فانتقل إلى الخطوة التالية.تحديث المخزن
على Debian وUbuntu:
apt updateثمapt install --only-upgrade ca-certificates، ثمupdate-ca-certificates. وعلى RHEL ومشتقاتها:dnf upgrade ca-certificatesثمupdate-ca-trust. وعلى Alpine:apk upgrade ca-certificates.التأكد من اختفاء الشهادات المحذوفة
ls /usr/share/ca-certificates/mozilla | grep -i -E 'emSign_ECC_Root_CA_-_G3|Comodo_AAA'ls /etc/ssl/certs | grep -i -E 'emSign_ECC_Root_CA_-_G3|Comodo_AAA'
بعد تحديث يزيل الشهادتين اللتين سمتهما Debian لا يجب أن يخرج أي سطر. يستهدف النمط الشهادتين اللتين سمتهما نشرة Debian فقط، لأن جذور emSign وComodo سليمة أخرى تبقى موجودة بشكل مشروع. والسطر الظاهر يدل على مخزن بقي على النسخة القديمة، أو على مجلد يُغذى يدوياً. تحقق من أسماء الملفات الفعلية على جهاز محدَّث.اختبار سلسلة من الخادم
openssl s_client -connect www.your-domain.com:443 -showcertsيعرض كل شهادة مرسلة وينتهي بالسطرVerify return code. الرمز 0 يعني أن المخزن المحلي يقبل السلسلة. أكمل ذلك بـcurl -v https://www.your-domain.comواقرأ السطرSSL certificate verify ok.جرد الحزم خارج مخزن النظام
curl-config --caيعطي مسار حزمة curl.python3 -c "import certifi; print(certifi.where())"يعطي مسار حزمة Python.echo $NODE_EXTRA_CA_CERTSيعرض إضافات Node إن وجدت.readlink -f $(which java)يقود إلى JDK الذي مخزنهlib/security/cacerts.تحديث certifi
pip show certifiيعطي الإصدار المثبت، وpython3 -m pip install --upgrade certifiيحدثه. وتدرج صفحة المرجع certifi 2026.10.19 ضمن الإصدارات المصححة. كرر العملية في كل بيئة افتراضية، لأن لكل منها نسختها.فحص مخزن Java
keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit | grep -i -E 'emsign ecc|aaa'يبحث عن الإدخالات المعنية؛ تختلف الأسماء المستعارة بحسب JDK، لذا قارنها بقائمة صفحة المرجع. وكان تصحيح OpenJDK معلقاً في تاريخ تلك الصفحة: فإن وُجد إدخال معني فسجل الجهاز «بانتظار المصدر» لا «مصحَّحاً».تسجيل النتيجة في تدقيقك الشهري
سطر لكل خادم: التاريخ وإصدار ca-certificates ومسارات الحزم ونتيجة اختبار السلسلة. هذا السجل هو ما تعرضه على العميل حين يسأل عما جرى فحصه، ويدخل في قائمة التدقيق الشهري لخوادم VPS الخاصة بعملائك.
أين تبحث، مكوناً بعد مكون
مرّر الجدول أفقيًا
| المكوّن | أين توجد قائمة الثقة | أمر الفحص |
|---|---|---|
| نظام Debian وUbuntu | الحزمة ca-certificates والمجلد /etc/ssl/certs | `dpkg -l ca-certificates` |
| نظام RHEL ومشتقاته | الحزمة ca-certificates ومخزن يديره update-ca-trust | `rpm -q ca-certificates` |
| curl | مخزن النظام أو حزمة البناء | `curl-config --ca` |
| Python وpip | وحدة certifi المستقلة عن النظام | `python3 -c "import certifi; print(certifi.where())"` |
| Node.js | قائمة مدمجة في الملف التنفيذي مع NODE_EXTRA_CA_CERTS | `echo $NODE_EXTRA_CA_CERTS` |
| Java | ملف cacerts في JDK | `keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit` |
| حاوية Docker | /etc/ssl/certs الخاص بكل صورة | `docker run --rm IMAGE ls /etc/ssl/certs` |
الحاويات: تصحيح المضيف لا يعبر إليها
لا ترث الحاوية مخزن مضيفها. إنها تحمل مخزن صورتها الأساسية، مجمداً يوم البناء. لذلك فإن تحديث ca-certificates على الخادم لا يغير شيئاً في حاوياتك. لفحص صورة نفّذ docker run --rm IMAGE ls /etc/ssl/certs، أو docker run --rm IMAGE dpkg -l ca-certificates إن كانت الصورة مبنية على Debian أو Ubuntu.
والعلاج هو إعادة البناء: الأمر docker build --pull --no-cache -t my-application:2026-10 . يسحب أحدث صورة أساسية ويعيد طبقة الشهادات. وبدون --pull يعيد Docker استخدام الأساس المخزن مؤقتاً، فتعيد بناء العيب نفسه. ثم أعد النشر وكرر الفحص على الحاوية العاملة. وتذكر الصور الخارجية (قاعدة بيانات أو وسيط أو أداة مراقبة) التي لا تبنيها: على ناشرها إصدار نسخة جديدة، وعليك التحقق من ذلك.
إذا كانت شهادة عميل ترتبط بهذه السلطات
هناك حالتان ويجب الفصل بينهما. الأولى: شهادة صدرت لعميلك أو لك وقّعتها إحدى الوسيطات المعنية. اقرأ الجهة المصدرة بـ openssl x509 -in certificat.pem -noout -subject -issuer -dates، ثم السلسلة المقدمة بـ openssl s_client -connect www.your-domain.com:443 -showcerts. وتنشر صفحة المرجع قائمة الوسيطات المتضررة (الملف impacted-intermediates.json): قارنها بما تقرأه. فإن كانت الجهة المصدرة فيها فاطلب من السلطة المصدرة إعادة إصدار ضمن سلسلة أخرى، دون انتظار انتهاء الصلاحية.
الحالة الثانية: شريك يتصل بك بشهادة عميل (mTLS) ويقبلها خادمك لأن مخزنه يحوي سلطة معنية. بعد التحديث قد يُرفض هذا الشريك، وهذا هو السلوك المقصود لكن يجب الإعلان عنه. نبّهه قبل ذلك، واسرد شهادات العملاء الفعالة، واحتفظ بتاريخ الاستبدال.
اختبر قبل التحديث وبعده على مضيفين حقيقيين
قد يؤدي حذف جذر إلى كسر سلاسل سليمة ترتبط به. قبل التحديث نفّذ curl -sS -o /dev/null -w '%{http_code}\n' https://www.your-domain.com على ثلاثة أو أربعة مضيفين تستدعيهم تطبيقاتك فعلاً، ثم أعد الأمر نفسه بعده. فالرمز المتغير أو خطأ التحقق يُعالج فوراً على خادم واحد، لا في الإنتاج صباح يوم اثنين.
استكشاف الأخطاء: الرسائل التي ستراها
بعد التحديث تعود أربع رسائل. curl: (60) SSL certificate problem: unable to get local issuer certificate: الخادم البعيد يرسل سلسلة ناقصة، أو كانت سلسلته تمر بشهادة محذوفة الآن. اختبر بـ openssl s_client -showcerts ثم اطلب من مسؤول الخدمة إصلاح سلسلته.
ssl.SSLCertVerificationError: CERTIFICATE_VERIFY_FAILED في Python: يستخدم المفسر مخزن certifi أو مخزن النظام بحسب التطبيق. اقرأ المسار بـ certifi.where() وحدّث المكوّن الصحيح.
PKIX path building failed: unable to find valid certification path to requested target في Java: الملف cacerts لا يحوي السلطة المتوقعة أو استُبدل. تحقق بـ keytool ثم أعد تشغيل JVM.
Verify return code: 20 (unable to get local issuer certificate) في openssl s_client: لم تعد السلطة في /etc/ssl/certs. وإذا كان الموقع سليماً فهذه إشارة تُعالج على الخادم البعيد، لا تُتجاوز بتعطيل التحقق.
ما زال معلقاً، ومن يتحمل ماذا
في تاريخ صفحة المرجع، المحدّثة في 28 أكتوبر 2026، كانت مكتبة NSS مصححة بالإصدار 3.131.1 وحزمة curl مصححة منذ 20 أكتوبر 2026، لكن تصحيح OpenJDK كان معلقاً، وبقيت أدوات سطر الأوامر من Apple تثق بالشهادات. أعد قراءة تلك الصفحة قبل أن تقول لعميل إن كل شيء صُحح: فالحالة تتغير، ويجب أن يذكر تقريرك تاريخ الفحص.
بالنسبة لوكالة، التقسيم بسيط. تحتفظ بعلاقتك مع العميل وبالتقرير الذي يثبت ما فُحص. أما الفحص نفسه فيجري جهازاً بعد جهاز. وإن كنت تدير خوادمك الخاصة فالتقرير نفسه دون العميل: سطر لكل جهاز مع التاريخ.