
foxcage — Updated!
Запустите Firefox в rootless-контейнере Podman с удалёнными capabilities, изолированной сетью и эфемерным хранилищем, чтобы локализовать побеги из песочницы и предотвратить компрометацию хоста.
foxcage
Запускайте Firefox в rootless-контейнере Podman для изоляции безопасности. Ваш браузер работает практически без Linux-возможностей (capabilities), в собственном пользовательском и сетевом пространстве имён, изолированном от хоста — при этом сохраняя полное аппаратное ускорение GPU, звук и поддержку DRM.
Зачем нужен foxcage?
Firefox уже имеет многопроцессную песочницу, которая изолирует рендереры веб-контента с помощью пространств имён Linux и seccomp-bpf. Для большинства угроз этого достаточно. foxcage добавляет вторую стену: если злоумышленник эксплуатирует уязвимость, обходящую песочницу Firefox (такое случается — для этого существуют CVE), он попадает в изолированный контейнер, а не в вашу полноценную пользовательскую сессию.
От чего защищает foxcage
- Доступ к файлам после эксплуатации. Побег из песочницы в обычном Firefox даёт доступ ко всему, что может прочитать ваш пользователь:
~/.ssh,~/.gnupg, профили браузеров для других браузеров, базы данных менеджеров паролей, документы, исходный код. В foxcage злоумышленник видит только то, что вы явно смонтировали внутрь. - Остаточные следы на диске. Эфемерный контейнер
@tmpне оставляет на диске никаких следов после закрытия окна — включая расширения, состояние HSTS, кэш TLS-сессий и DNS-кэш, которые Firefox в режиме приватного просмотра всё равно сохраняет. Несколько контейнеров@tmpработают одновременно, не мешая друг другу. - Постоянство (persistence). В обычном Firefox вредоносное ПО может записываться в
~/.config/autostart,~/.bashrc, cron или куда угодно ещё, чтобы пережить перезагрузку. Эфемерный контейнер foxcage (--rm) означает, что ничего не сохраняется, если вы не смонтировали это через bind mount. - Латеральное перемещение по сети. По умолчанию контейнер не может опрашивать сервисы на
localhost. В обычном Firefox побег из песочницы даёт полный сетевой доступ. (Используйте[network] mode = "host", если контейнеру нужен доступ к localhost, например для локальной разработки — но учтите предостережение в разделе «Сеть»: host-режим также открывает доступ к абстрактным Unix-сокетам хоста.) - Повышение привилегий. Контейнер отбрасывает все Linux-возможности, кроме
CAP_SYS_CHROOT, и блокирует получение новых привилегий. Setuid-бинарники, эксплойты ядра через редкие системные вызовы и подобные пути повышения привилегий отсечены.
От чего foxcage не защищает
- Атаки на уровне браузера. Фишинг, вредоносные расширения и всё, что действует в рамках обычной функциональности Firefox, не затрагивается — foxcage изолирует контейнер от хоста, а не пользователя от браузера.
- Каталоги, смонтированные через bind mount. Всё, что вы монтируете внутрь (
profile,downloads_dir, дополнительные bind mounts), полностью доступно скомпрометированному браузеру. Если вы смонтируете каталог профиля хоста, злоумышленник сможет вмешиваться в него так же, как в обычном Firefox. - Запись звука через PulseAudio. Сокет PulseAudio монтируется в контейнер через bind mount. Хотя на уровне файловой системы он смонтирован только для чтения, Unix-доменные сокеты двунаправленны — скомпрометированный процесс всё равно может отправлять запросы на запись через сокет. Побег из песочницы браузера потенциально может записывать звук с микрофона хоста.
- Эксплойты Wayland-композитора. Сокет Wayland передаётся внутрь. Композиторы Wayland изолируют клиентов друг от друга по замыслу, но уязвимость в самом композиторе будет достижима.
Конфигурация безопасности
Контейнер запускается со следующими параметрами:
- Все Linux-возможности отброшены (только
CAP_SYS_CHROOTдобавлен обратно для песочницы контента Firefox;CAP_SETUID/CAP_SETGIDдобавляются временно, когда настроенinit.root) no-new-privilegesдля предотвращения повышения привилегий- Rootless-пространство имён пользователя (
--userns keep-id) - Приватный
/dev/shm(не общий с хостом) — настраиваемый размер черезshm_size - Изолированная сеть через pasta с блокировкой loopback хоста по умолчанию
- DNS использует 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.*и (для форков) собственное пространство имён форка (например,org.librewolf.*) — сервисы сессии, такие как связка ключей (keyring) и агенты SSH/GPG, заблокированы - Доступ к порталам широкий.
org.freedesktop.portal.Desktopразрешён целиком, потому что именно так работают выбор файлов, «открыть ссылку в другом приложении» и демонстрация экрана. Он также открываетRemoteDesktop(синтетические клавиатура/мышь для всей сессии),CameraиLocation. Они ограничиваются диалогами одобрения вашего рабочего стола, а не foxcage — и запросRemoteDesktopпохож на запрос демонстрации экрана, поэтому читайте диалоги одобрения перед их принятием. Уxdg-dbus-proxyнет правила «запретить один интерфейс», поэтому сужение этого означает перечисление всех интерфейсов, которые нужны Firefox; см.docs/DESIGN.mdо том, почему это не делается по умолчанию - Все bind mounts (
profile,downloads_dir, дополнительные[mounts] bind) используютnosuid,noexec - Загрузка браузера проверяется по GPG-подписям: Firefox — по подписанным SHA-512 контрольным суммам Mozilla, LibreWolf — по отдельной подписи сопровождающих LibreWolf плюс сопутствующим SHA-256. Проверка строже, чем
gpg --verify, который возвращает 0 для подписи, сделанной отозванным ключом, и для любого ключа в связке. foxcage дополнительно требует, чтобы подпись вела к закреплённому основному ключу, и отказывается от любого релиза, подписанного субключом, который его владелец отозвал как скомпрометированный — см. Отозванные ключи подписи - Эфемерный контейнер (
--rm) — записи в файловую систему теряются при выходе - Никакие устройства хоста (веб-камера, ключи безопасности, принтеры) не передаются внутрь, если явно не включены
Каждая включённая вами опция [network] и [mounts] обменивает часть изоляции на удобство. Значения по умолчанию — это наиболее ограничительная конфигурация, которая всё ещё даёт вам рабочий браузер.
Требования
- Python 3.11+
- Podman (rootless)
- Wayland-композитор (X11 не поддерживается)
- pasta (
sudo apt install passt) — если толькоnetwork.mode = "host" - xdg-dbus-proxy (
sudo apt install xdg-dbus-proxy) - PulseAudio или PipeWire с совместимостью с PulseAudio (для звука)
- GPU с поддержкой DRI — необязательно; без
/dev/drifoxcage выдаёт предупреждение, и Firefox рендерит программно. Драйверы VA-API для Intel, AMD и nouveau установлены в образе, поэтому аппаратное декодирование видео работает без пакетов драйверов хоста — см. Аппаратное декодирование видео
Запускайте foxcage как обычного пользователя рабочего стола, а не от root или через sudo — песочница отображает вашего пользователя в контейнер, а запуск от root устраняет изоляцию, ради которой существует foxcage. Он отказывается запускаться от root.
Протестированная среда: Debian 13 (Trixie) с GNOME 3. Другие дистрибутивы Linux и Wayland-композиторы могут работать, но не были протестированы.
Установка
foxcage — это один Python-скрипт без зависимостей за пределами стандартной библиотеки Python. Скопируйте его в каталог из вашего PATH:```sh
sudo cp foxcage /usr/local/bin/foxcage
Или для установки в каталоге пользователя:```sh
cp foxcage ~/.local/bin/foxcage
Убедитесь, что скрипт исполняемый (chmod +x foxcage).