
foxcage — Mis à jour !
Exécutez Firefox dans un conteneur Podman rootless avec des capabilities supprimées, un réseau isolé et un stockage éphémère afin de contenir les évasions de sandbox et d'empêcher la compromission de l'hôte.
foxcage
Exécutez Firefox dans un conteneur Podman sans root pour l'isolation de sécurité. Votre navigateur s'exécute avec presque aucune capacité Linux, dans son propre espace utilisateur et réseau, isolé de l'hôte — tout en conservant une accélération GPU complète, l'audio et la prise en charge des DRM.
Pourquoi foxcage ?
Firefox dispose déjà d'un sandbox multi-processus qui isole les moteurs de rendu de contenu web à l'aide d'espaces de noms Linux et de seccomp-bpf. Pour la plupart des menaces, cela est efficace. foxcage ajoute une seconde paroi : si un attaquant exploite une vulnérabilité qui contourne le sandbox de Firefox (ce qui arrive — il existe des CVE pour cela), il atterrit dans un conteneur verrouillé au lieu de votre session utilisateur complète.
Ce contre quoi foxcage protège
- Accès aux fichiers après exploitation. Une évasion du sandbox sur Firefox nu donne accès à tout ce que votre utilisateur peut lire :
~/.ssh,~/.gnupg, les profils de navigateur pour d'autres navigateurs, les bases de données de gestionnaires de mots de passe, les documents, le code source. Avec foxcage, l'attaquant ne voit que ce que vous avez explicitement monté. - Résidus de suivi sur disque. La cage éphémère
@tmpne laisse aucune trace sur le disque après la fermeture de la fenêtre — y compris les extensions, l'état HSTS, le cache de session TLS et le cache DNS que la navigation privée de Firefox persiste encore. Plusieurs cages@tmps'exécutent simultanément sans interférer les unes avec les autres. - Persistance. Sur Firefox nu, un logiciel malveillant peut écrire dans
~/.config/autostart,~/.bashrc, cron, ou ailleurs pour survivre à un redémarrage. Le conteneur éphémère de foxcage (--rm) signifie que rien ne persiste à moins que vous ne l'ayez monté par bind. - Mouvement réseau latéral. Par défaut, le conteneur ne peut pas sonder les services sur
localhost. Sur Firefox nu, une évasion du sandbox dispose d'un accès réseau complet. (Utilisez[network] mode = "host"si une cage a besoin d'un accès localhost, par exemple pour le développement local — mais voir l'avertissement sous « Réseau » : le mode hôte expose également les sockets Unix abstraits de l'hôte.) - Élévation de privilèges. Le conteneur abandonne toutes les capacités Linux sauf
CAP_SYS_CHROOTet bloque l'acquisition de nouveaux privilèges. Les binaires setuid, les exploits du noyau via des appels système obscurs, et les chemins d'élévation similaires sont coupés.
Ce contre quoi foxcage ne protège pas
- Attaques au niveau du navigateur. Le phishing, les extensions malveillantes et tout ce qui opère dans le fonctionnement normal de Firefox n'est pas affecté — foxcage isole le conteneur de l'hôte, pas l'utilisateur du navigateur.
- Répertoires montés par bind. Tout ce que vous montez (
profile,downloads_dir, montages bind supplémentaires) est entièrement accessible à un navigateur compromis. Si vous montez un répertoire de profil hôte, un attaquant peut le falsifier tout comme sur Firefox nu. - Capture audio via PulseAudio. Le socket PulseAudio est monté par bind dans le conteneur. Bien qu'il soit monté en lecture seule au niveau du système de fichiers, les sockets de domaine Unix sont bidirectionnels — un processus compromis peut toujours envoyer des demandes d'enregistrement via le socket. Une évasion du sandbox du navigateur pourrait potentiellement enregistrer l'audio du microphone de l'hôte.
- Exploits du compositeur Wayland. Le socket Wayland est transmis. Les compositeurs Wayland isolent les clients les uns des autres par conception, mais une vulnérabilité dans le compositeur lui-même serait accessible.
Configuration de sécurité
Le conteneur s'exécute avec :
- Toutes les capacités Linux abandonnées (seulement
CAP_SYS_CHROOTrajoutée pour le sandbox de contenu de Firefox ;CAP_SETUID/CAP_SETGIDajoutées temporairement lorsqueinit.rootest configuré) no-new-privilegespour empêcher l'élévation de privilèges- Espace de noms utilisateur sans root (
--userns keep-id) /dev/shmprivé (non partagé avec l'hôte) — taille configurable viashm_size- Réseau isolé via pasta avec le loopback de l'hôte bloqué par défaut
- Le DNS utilise le DNS de l'hôte par défaut (configurable via
network.dns) - Seuls les sockets spécifiques de
XDG_RUNTIME_DIRsont montés par bind (Wayland, PulseAudio, PipeWire et le proxy D-Bus filtré) — le répertoire d'exécution complet de l'hôte n'est jamais exposé - L'accès au bus de session D-Bus de l'hôte est toujours médié par un
xdg-dbus-proxyfiltré s'exécutant sur l'hôte. Seulsorg.freedesktop.Notifications,org.freedesktop.portal.Desktop,org.mozilla.*, et (pour les forks) l'espace de noms propre du fork (par exempleorg.librewolf.*) sont accessibles — les services de session comme le trousseau et l'agent SSH/GPG sont bloqués - L'accès au portail est large.
org.freedesktop.portal.Desktopest autorisé dans son ensemble, car c'est ainsi que fonctionnent le sélecteur de fichiers, « ouvrir le lien dans une autre application » et le partage d'écran. Il expose égalementRemoteDesktop(clavier/souris synthétiques pour toute la session),CameraetLocation. Ceux-ci sont contrôlés par les propres dialogues d'approbation de votre bureau plutôt que par foxcage — et l'inviteRemoteDesktopressemble à l'invite de partage d'écran, alors lisez les dialogues d'approbation avant de les accepter.xdg-dbus-proxyn'a pas de règle « refuser une interface », donc restreindre cela signifie énumérer chaque interface dont Firefox a besoin ; voirdocs/DESIGN.mdpour savoir pourquoi cela n'est pas fait par défaut - Tous les montages bind (
profile,downloads_dir,[mounts] bindsupplémentaires) utilisentnosuid,noexec - Le téléchargement du navigateur est vérifié par rapport aux signatures GPG : Firefox contre les sommes SHA-512 signées de Mozilla, LibreWolf contre la signature détachée des mainteneurs LibreWolf plus le SHA-256 associé. La vérification est plus stricte que
gpg --verify, qui sort avec 0 pour une signature faite par une clé révoquée et pour toute clé du trousseau. foxcage exige en outre que la signature remonte à la clé primaire épinglée, et refuse toute version signée par une sous-clé que son propriétaire a révoquée comme compromise — voir Clés de signature révoquées - Conteneur éphémère (
--rm) — les écritures du système de fichiers sont perdues à la sortie - Aucun périphérique hôte (webcam, clés de sécurité, imprimantes) transmis sauf s'il est explicitement activé
Chaque option [network] et [mounts] que vous activez échange une partie de l'isolation contre de la commodité. Les valeurs par défaut sont la configuration la plus restrictive qui vous donne tout de même un navigateur utilisable.
Prérequis
- Python 3.11+
- Podman (sans root)
- Compositeur Wayland (X11 n'est pas pris en charge)
- pasta (
sudo apt install passt) — sauf sinetwork.mode = "host" - xdg-dbus-proxy (
sudo apt install xdg-dbus-proxy) - PulseAudio ou PipeWire avec compatibilité PulseAudio (pour l'audio)
- GPU avec prise en charge DRI — facultatif ; sans
/dev/dri, foxcage émet un avertissement et Firefox effectue le rendu en logiciel. Les pilotes VA-API pour Intel, AMD et nouveau sont installés dans l'image, donc le décodage vidéo matériel fonctionne sans paquets de pilotes hôte — voir Décodage vidéo matériel (VA-API)
Exécutez foxcage en tant que votre utilisateur de bureau normal, pas en tant que root ou via sudo — le sandbox mappe votre utilisateur dans le conteneur, et s'exécuter en tant que root supprime l'isolation que foxcage existe pour fournir. Il refuse de démarrer en tant que root.