
foxcage — Updated!
Execute o Firefox em um contêiner Podman rootless com capabilities removidas, rede isolada e armazenamento efêmero para conter fugas da sandbox e evitar o comprometimento do host.
foxcage
Execute o Firefox em um contêiner Podman sem root para isolamento de segurança. Seu navegador roda com quase nenhuma capability do Linux, em seu próprio namespace de usuário e de rede, isolado do host — enquanto ainda tem aceleração de GPU completa, áudio e suporte a DRM.
Por que foxcage?
O Firefox já possui um sandbox multiprocesso que isola os renderizadores de conteúdo web usando namespaces do Linux e seccomp-bpf. Para a maioria das ameaças, isso é eficaz. O foxcage adiciona uma segunda parede: se um atacante explorar uma vulnerabilidade que escape do sandbox do Firefox (o que acontece — existem CVEs para isso), ele cairá dentro de um contêiner bloqueado em vez da sua sessão de usuário completa.
O que o foxcage protege contra
- Acesso a arquivos pós-exploração. Uma fuga de sandbox no Firefox puro dá acesso a tudo que seu usuário pode ler:
~/.ssh,~/.gnupg, perfis de navegador de outros navegadores, bancos de dados de gerenciadores de senhas, documentos, código-fonte. No foxcage, o atacante vê apenas o que você montou explicitamente. - Resíduos de rastreamento em disco. A gaiola efêmera
@tmpdeixa zero vestígios no disco após o fechamento da janela — incluindo extensões, estado HSTS, cache de sessão TLS e cache DNS que a Navegação Privada do Firefox ainda persiste. Várias gaiolas@tmprodam simultaneamente sem interferir umas nas outras. - Persistência. No Firefox puro, malware pode gravar em
~/.config/autostart,~/.bashrc, cron ou em qualquer outro lugar para sobreviver a uma reinicialização. O contêiner efêmero do foxcage (--rm) significa que nada persiste a menos que você o tenha montado via bind. - Movimento lateral na rede. Por padrão, o contêiner não pode sondar serviços em
localhost. No Firefox puro, uma fuga de sandbox tem acesso total à rede. (Use[network] mode = "host"se uma gaiola precisar de acesso a localhost, por exemplo, para desenvolvimento local — mas veja a ressalva em "Rede": o modo host também expõe os sockets Unix abstratos do host.) - Escalonamento de privilégios. O contêiner remove todas as capabilities do Linux, exceto
CAP_SYS_CHROOT, e bloqueia a aquisição de novos privilégios. Binários setuid, exploits de kernel via syscalls obscuras e caminhos de escalonamento semelhantes são cortados.
O que o foxcage não protege contra
- Ataques no nível do navegador. Phishing, extensões maliciosas e qualquer coisa que opere dentro da funcionalidade normal do Firefox não é afetada — o foxcage isola o contêiner do host, não o usuário do navegador.
- Diretórios montados via bind. Qualquer coisa que você monte (
profile,downloads_dir, montagens bind extras) é totalmente acessível a um navegador comprometido. Se você montar um diretório de perfil do host, um atacante pode adulterá-lo assim como no Firefox puro. - Captura de áudio via PulseAudio. O socket do PulseAudio é montado via bind no contêiner. Embora seja montado somente leitura no nível do sistema de arquivos, sockets de domínio Unix são bidirecionais — um processo comprometido ainda pode enviar solicitações de gravação através do socket. Uma fuga de sandbox do navegador poderia potencialmente gravar áudio do microfone do host.
- Exploits do compositor Wayland. O socket Wayland é repassado. Os compositores Wayland isolam clientes uns dos outros por design, mas uma vulnerabilidade no próprio compositor seria alcançável.
Configuração de segurança
O contêiner roda com:
- Todas as capabilities do Linux removidas (apenas
CAP_SYS_CHROOTadicionada de volta para o sandbox de conteúdo do Firefox;CAP_SETUID/CAP_SETGIDadicionadas temporariamente quandoinit.rootestá configurado) no-new-privilegespara impedir escalonamento de privilégios- Namespace de usuário sem root (
--userns keep-id) /dev/shmprivado (não compartilhado com o host) — tamanho configurável viashm_size- Rede isolada via pasta com loopback do host bloqueado por padrão
- DNS usa o DNS do host por padrão (configurável via
network.dns) - Apenas sockets específicos de
XDG_RUNTIME_DIRsão montados via bind (Wayland, PulseAudio, PipeWire e o proxy D-Bus filtrado) — o diretório de runtime completo do host nunca é exposto - O acesso ao barramento de sessão D-Bus do host é sempre mediado por um
xdg-dbus-proxyfiltrado rodando no host. Apenasorg.freedesktop.Notifications,org.freedesktop.portal.Desktop,org.mozilla.*e (para forks) o namespace próprio do fork (por exemplo,org.librewolf.*) são alcançáveis — serviços de sessão como o keyring e o agente SSH/GPG são bloqueados - O acesso a portais é amplo.
org.freedesktop.portal.Desktopé permitido como um todo, porque é assim que o seletor de arquivos, "abrir link em outro aplicativo" e o compartilhamento de tela funcionam. Ele também expõeRemoteDesktop(teclado/mouse sintético para toda a sessão),CameraeLocation. Esses são controlados pelos diálogos de aprovação do seu próprio desktop, não pelo foxcage — e o prompt deRemoteDesktopse assemelha ao prompt de compartilhamento de tela, então leia os diálogos de aprovação antes de aceitá-los. Oxdg-dbus-proxynão tem regra de "negar uma interface", então restringir isso significa enumerar cada interface que o Firefox precisa; vejadocs/DESIGN.mdpara saber por que isso não é feito por padrão - Todas as montagens bind (
profile,downloads_dir,[mounts] bindextras) usamnosuid,noexec - Download do navegador verificado contra assinaturas GPG: Firefox contra as somas SHA-512 assinadas da Mozilla, LibreWolf contra a assinatura destacada dos Mantenedores do LibreWolf mais SHA-256 irmão. A verificação é mais rigorosa que
gpg --verify, que sai com 0 para uma assinatura feita por uma chave revogada e para qualquer chave no chaveiro. O foxcage adicionalmente exige que a assinatura encadeie até a chave primária fixada e recusa qualquer lançamento assinado por uma subchave que seu proprietário revogou como comprometida — veja Chaves de assinatura revogadas - Contêiner efêmero (
--rm) — gravações no sistema de arquivos são perdidas ao sair - Sem dispositivos do host (webcam, chaves de segurança, impressoras) repassados, a menos que habilitados explicitamente
Cada opção [network] e [mounts] que você habilitar troca algum isolamento por conveniência. Os padrões são a configuração mais restritiva que ainda oferece um navegador utilizável.
Requisitos
- Python 3.11+
- Podman (sem root)
- Compositor Wayland (X11 não é suportado)
- pasta (
sudo apt install passt) — a menos quenetwork.mode = "host" - xdg-dbus-proxy (
sudo apt install xdg-dbus-proxy) - PulseAudio ou PipeWire com compatibilidade com PulseAudio (para áudio)
- GPU com suporte a DRI — opcional; sem
/dev/dri, o foxcage avisa e o Firefox renderiza em software. Drivers VA-API para Intel, AMD e nouveau são instalados na imagem, então a decodificação de vídeo por hardware funciona sem pacotes de driver do host — veja Decodificação de vídeo por hardware
Execute o foxcage como seu usuário normal de desktop, não como root ou via sudo — o sandbox mapeia seu usuário para dentro do contêiner, e rodar como root remove o isolamento para o qual o foxcage existe. Ele se recusa a iniciar como root.
Ambiente testado: Debian 13 (Trixie) com GNOME 3. Outras distribuições Linux e compositores Wayland podem funcionar, mas não foram testados.
Instalação
O foxcage é um único script Python sem dependências fora da biblioteca padrão do Python. Copie-o para um diretório no seu PATH:```sh
sudo cp foxcage /usr/local/bin/foxcage
Ou para uma instalação local do usuário:```sh
cp foxcage ~/.local/bin/foxcage
Certifique-se de que o script é executável (chmod +x foxcage).