
foxcage — Updated!
شغّل Firefox في حاوية Podman rootless مع إسقاط الصلاحيات (capabilities)، وعزل الشبكة، وتخزين مؤقت (ephemeral) لاحتواء محاولات الهروب من بيئة العزل (sandbox) ومنع اختراق المضيف.
foxcage
شغّل Firefox داخل حاوية Podman بلا صلاحيات جذر (rootless) لعزل الأمان. يعمل متصفحك بقدرات Linux شبه معدومة، داخل مساحة اسم مستخدم وشبكة خاصة به، معزولًا عن المضيف — مع احتفاظه بتسريع GPU الكامل ودعم الصوت وDRM.
لماذا foxcage؟
يمتلك Firefox بالفعل صندوق رمل متعدد العمليات (multi-process sandbox) يعزل مُصيّرات محتوى الويب باستخدام مساحات أسماء Linux وseccomp-bpf. هذا فعّال ضد معظم التهديدات. يضيف foxcage جدارًا ثانيًا: إذا استغل مهاجم ثغرة تفلت من صندوق رمل Firefox (وهو ما يحدث — فهناك CVEs لذلك)، فإنه يهبط داخل حاوية مقفلة بدلًا من جلسة المستخدم الكاملة الخاصة بك.
ما يحمي منه foxcage
- الوصول إلى الملفات بعد الاستغلال. يمنح الفرار من صندوق الرمل على Firefox العاري وصولًا إلى كل ما يمكن لمستخدمك قراءته:
~/.ssh، و~/.gnupg، وملفات تعريف المتصفحات الأخرى، وقواعد بيانات مديري كلمات المرور، والمستندات، والشيفرة المصدرية. في foxcage، لا يرى المهاجم سوى ما قمت بتركيبه (mount) صراحةً. - بقايا التتبع على القرص. لا يترك القفص المؤقت
@tmpأي أثر على القرص بعد إغلاق النافذة — بما في ذلك الإضافات، وحالة HSTS، وذاكرة جلسات TLS المؤقتة، وذاكرة DNS المؤقتة التي لا يزال التصفح الخاص في Firefox يحتفظ بها. تعمل عدة أقفاص@tmpفي الوقت نفسه دون أن تتداخل مع بعضها. - الاستمرارية. على Firefox العاري، يمكن للبرمجيات الخبيثة الكتابة إلى
~/.config/autostartأو~/.bashrcأو cron أو أي مكان آخر للبقاء بعد إعادة التشغيل. أما الحاوية المؤقتة في foxcage (--rm) فتعني أن لا شيء يبقى ما لم تكن قد ربطته بـ bind-mount. - الحركة الجانبية على الشبكة. افتراضيًا، لا تستطيع الحاوية فحص الخدمات على
localhost. على Firefox العاري، يمتلك الفرار من صندوق الرمل وصولًا كاملًا إلى الشبكة. (استخدم[network] mode = "host"إذا احتاج قفص إلى الوصول إلى localhost، مثلًا للتطوير المحلي — لكن راجع التحذير تحت "Networking": وضع المضيف يعرّض أيضًا مقابس Unix المجردة (abstract Unix sockets) الخاصة بالمضيف.) - تصعيد الصلاحيات. تُسقط الحاوية جميع قدرات Linux عدا
CAP_SYS_CHROOTوتحجب اكتساب صلاحيات جديدة. تُقطع بذلك مسارات التصعيد المتمثلة في ثنائيات setuid واستغلال النواة عبر استدعاءات نظام غامضة وما شابه.
ما لا يحمي منه foxcage
- الهجمات على مستوى المتصفح. التصيد الاحتيالي، والإضافات الخبيثة، وأي شيء يعمل ضمن وظائف Firefox الطبيعية لا يتأثر — فـ foxcage يعزل الحاوية عن المضيف، لا المستخدم عن المتصفح.
- الأدلّة المرتبطة بـ bind-mount. كل ما تركبه (
profile، وdownloads_dir، وعمليات bind mount إضافية) متاح بالكامل لمتصفح مخترق. إذا ركّبت دليل ملف تعريف على المضيف، يمكن للمهاجم العبث به تمامًا كما على Firefox العاري. - التقاط الصوت عبر PulseAudio. يُربط مقبس PulseAudio داخل الحاوية بـ bind-mount. ورغم أنه مركّب للقراءة فقط على مستوى نظام الملفات، فإن مقابس نطاق Unix ثنائية الاتجاه — أي أن عملية مخترقة لا تزال قادرة على إرسال طلبات تسجيل عبر المقبس. وقد يتمكن الفرار من صندوق رمل المتصفح من تسجيل الصوت من ميكروفون المضيف.
- متطلبات Firefox الأخرى عبر D-Bus. يعتمد فتح الروابط في قفص قيد التشغيل على التحكم عن بُعد في Firefox عبر D-Bus، وعلى الوسيط (proxy) أن يسمح بكامل نطاق
org.mozilla.*من أجله (إذ لا يمكن التنبؤ بأمان بالاسم الدقيق الخاص بكل قفص). لذلك يمكن لقفص مخترق أن يفتح عناوين URL في أقفاصك الأخرى، بكوكيزها، أو في Firefox الذي تشغّله على المضيف. وعندما لا يكون Firefox المضيف قيد التشغيل، يمكنه أيضًا الاستيلاء على اسمه في D-Bus وتلقي الروابط الموجّهة إليه. راجع "D-Bus proxy" فيdocs/DESIGN.md. - استغلال مُركّبات Wayland. يُمرَّر مقبس Wayland عبر الحاوية. تعزل مُركّبات Wayland العملاء عن بعضهم بحكم التصميم، لكن ثغرة في المُركّب نفسه ستكون قابلة للوصول.
إعدادات الأمان
تعمل الحاوية بـ:
- إسقاط جميع قدرات Linux (مع إعادة إضافة
CAP_SYS_CHROOTفقط من أجل sandbox المحتوى في Firefox؛ وتُضافCAP_SETUID/CAP_SETGIDمؤقتًا عند تكوينinit.root) no-new-privilegesلمنع تصعيد الصلاحيات- Rootless user namespace (
--userns keep-id) /dev/shmخاص (غير مشترك مع المضيف) — حجم قابل للتكوين عبرshm_size- شبكة معزولة عبر pasta مع حظر loopback الخاص بالمضيف افتراضيًا
- يستخدم DNS الخاص بالمضيف افتراضيًا (قابل للتكوين عبر
network.dns) - تُربط فقط مقابس محددة من
XDG_RUNTIME_DIR(Wayland وPulseAudio وPipeWire ووكيل D-Bus المفلتر) — ولا يُكشف دليل runtime الكامل للمضيف أبدًا - الوصول إلى ناقل جلسة D-Bus الخاص بالمضيف يتوسط فيه دائمًا
xdg-dbus-proxyمفلتر يعمل على المضيف. لا يمكن الوصول إلا إلىorg.freedesktop.Notificationsوorg.freedesktop.portal.Desktopوorg.mozilla.*و(بالنسبة للـ forks) مساحة الأسماء الخاصة بالـ fork نفسه (مثلorg.librewolf.*) — وتُحظر خدمات الجلسة مثل keyring ووكيل SSH/GPG - الوصول إلى Portal واسع. يُسمح بـ
org.freedesktop.portal.Desktopككل، لأن هذه هي الطريقة التي يعمل بها منتقي الملفات و"فتح الرابط في تطبيق آخر" ومشاركة الشاشة. وهو يكشف أيضًا عنRemoteDesktop(لوحة مفاتيح/فأرة اصطناعية للجلسة بأكملها) وCameraوLocation. وتُقيَّد هذه بنوافذ الموافقة الخاصة بسطح المكتب لديك بدلًا من foxcage — ونافذةRemoteDesktopتشبه نافذة مشاركة الشاشة، لذا اقرأ نوافذ الموافقة قبل قبولها. لا توجد فيxdg-dbus-proxyقاعدة "رفض واجهة واحدة"، لذا فإن تضييق ذلك يعني تعداد كل واجهة يحتاجها Firefox؛ راجعdocs/DESIGN.mdلمعرفة سبب عدم القيام بذلك افتراضيًا - جميع عمليات bind mount (
profileوdownloads_dirو[mounts] bindالإضافية) تستخدمnosuid,noexec - التحقق من تنزيل المتصفح مقابل توقيعات GPG: Firefox مقابل مجاميع التحقق SHA-512 الموقعة من Mozilla، وLibreWolf مقابل التوقيع المنفصل من LibreWolf Maintainers بالإضافة إلى SHA-256 المجاور. والتحقق أكثر صرامة من
gpg --verify، الذي يخرج بالرمز 0 لتوقيع صادر عن مفتاح ملغى ولأي مفتاح في keyring. ويشترط foxcage إضافةً إلى ذلك أن تتسلسل التوقيعات إلى المفتاح الأساسي المثبّت، ويرفض أي إصدار موقّع بمفتاح فرعي ألغاه مالكه باعتباره مخترقًا — راجع Revoked signing keys - حاوية مؤقتة (
--rm) — تُفقد الكتابات على نظام الملفات عند الخروج - لا تُمرَّر أجهزة المضيف (كاميرا الويب، مفاتيح الأمان، الطابعات) ما لم تُفعَّل صراحةً
كل خيار [network] و[mounts] تفعّله يقايض بعض العزل مقابل الراحة. والإعدادات الافتراضية هي التكوين الأكثر تقييدًا الذي يمنحك مع ذلك متصفحًا قابلًا للاستخدام.
المتطلبات
- Python 3.11+
- Podman (rootless)
- Wayland compositor (X11 غير مدعوم)
- pasta (
sudo apt install passt) — ما لم يكنnetwork.mode = "host" - xdg-dbus-proxy (
sudo apt install xdg-dbus-proxy) - PulseAudio أو PipeWire مع توافق PulseAudio (للصوت)
- GPU مع دعم DRI — اختياري؛ فبدون
/dev/driيحذّر foxcage ويعرض Firefox برمجيًا. تُثبَّت برامج تشغيل VA-API لـ Intel وAMD وnouveau في الصورة، لذا يعمل فك ترميز الفيديو العتادي دون حزم برامج تشغيل المضيف — راجع Hardware video decoding
شغّل foxcage كمستخدم سطح المكتب العادي، وليس كـ root أو عبر sudo — إذ يربط الـ sandbox مستخدمك داخل الحاوية، والتشغيل كـ root يزيل العزل الذي وُجد foxcage لتوفيره. وهو يرفض البدء كـ root.
البيئة المختبَرة: Debian 13 (Trixie) مع GNOME 3. قد تعمل توزيعات Linux الأخرى وWayland compositors الأخرى لكنها لم تُختبر.
التثبيت
foxcage هو سكربت Python واحد بلا اعتماديات خارج مكتبة Python القياسية. انسخه إلى دليل في PATH الخاص بك:
sudo cp foxcage /usr/local/bin/foxcage
أو لتثبيت محلي للمستخدم:
cp foxcage ~/.local/bin/foxcage
تأكد من أن السكربت قابل للتنفيذ (chmod +x foxcage).
تحقق من الإصدار الذي لديك باستخدام foxcage --version — مفيد عند الإبلاغ عن مشكلة، لأن foxcage يُثبَّت عن طريق نسخ ملف واحد.
الاستخدام
./foxcage
عند التشغيل الأول، يبني السكربت صورة الحاوية (يُنزّل Firefox من Mozilla، ويثبّت تبعيات Debian الأساسية) ثم يشغّل Firefox. في عمليات التشغيل اللاحقة، يتحقق foxcage من تحديثات Firefox ويعيد بناء الصورة تلقائيًا عند توفر إصدار جديد. تُعاد الصورة بناؤها أيضًا بشكل دوري (كل 7 أيام افتراضيًا) لالتقاط تحديثات حزم النظام. إذا فشل فحص التحديثات (خطأ في الشبكة، انتهاء المهلة)، يُسجَّل تحذير وتُستخدم الصورة الحالية — ولا يُحظر بدء التشغيل أبدًا.
مرّر الوسائط إلى Firefox:
./foxcage https://example.com
اجمع بين قفص مسمّى مع أعلام Firefox: