feat(max): add MAX messenger package, sandboxed with Firejail

MAX is the Russian state-affiliated messenger; the official Qt6 client is
repacked from download.max.ru with no independent security track record,
so it never runs unsandboxed. /usr/bin/max is a wrapper (not a symlink)
that always launches through `firejail --profile=max`; the .desktop Exec
goes through the same wrapper so there's no launch path that bypasses it.
The profile hides the rest of the home directory behind private ~/.config,
~/.cache and ~/.local/share/max subdirectories, drops capabilities, enables
seccomp, blocks system D-Bus, and blacklists the standalone crashpad_handler
crash-report uploader. Full elimination of first-party telemetry isn't
claimed or possible from the sandbox layer alone — documented in LICENSE.

Also wires up repo-wide bookkeeping now that all three package changes
(telegram-desktop -> telegram rename, vk-messenger, max) are in: README
package count/catalog rows, docs/maintenance.md naming table and directory
count, and tools/package_updates.sh + tools/validate_repo.py package lists.
This commit is contained in:
Александр
2026-07-25 18:02:25 +10:00
parent 6401c42a91
commit 73b5e87e95
12 changed files with 329 additions and 6 deletions
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
set -euo pipefail
package_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
repo_root="$(cd "${package_dir}/.." && pwd)"
exec "${repo_root}/tools/package_updates.sh" check "$(basename "$package_dir")"
+33
View File
@@ -0,0 +1,33 @@
Сведения о лицензии пакета max
Лицензия: Custom (проприетарная).
Исходный продукт: https://max.ru/
Официальный deb-репозиторий: https://download.max.ru/linux/deb/
Нюансы пакета:
- Пакет перепаковывает официальный Linux deb-артефакт MAX Messenger Client
из deb-репозитория max.ru; отдельного публичного репозитория исходников
или GitHub-релиза у продукта нет.
- Приложение собрано на Qt6 и распространяется полностью самодостаточным
бандлом (собственные библиотеки Qt в `lib64/`).
- Пакет запускает приложение только через Firejail-песочницу (профиль
`/etc/firejail/max.profile`): домашний каталог пользователя виден
приложению только через отдельные `~/.config/max`, `~/.cache/max`,
`~/.local/share/max`; capabilities сброшены, seccomp включён,
системная D-Bus недоступна. Отдельный процесс `crashpad_handler`
(сбор и отправка крэш-дампов) заблокирован явным `blacklist`, чтобы
ограничить исходящую телеметрию, не относящуюся к функциям обмена
сообщениями.
- Полная гарантия отсутствия любой сетевой телеметрии невозможна:
трафик самого мессенджера к серверам max.ru неотличим от служебного
на уровне песочницы. Firejail ограничивает доступ к системе и файлам,
а не содержимое протокола приложения.
- Для полноценной работы требуется учетная запись, привязанная к
российскому номеру телефона.
- Использование мессенджера, учетной записи и сетевых функций
регулируется условиями MAX.
- Пакет помечен как несвободный через `nonfree=1`.
Официальные условия:
https://legal.max.ru/ps
https://legal.max.ru/pp
+105
View File
@@ -0,0 +1,105 @@
name='max'
version='26.24.0~75261'
release=1
summary='MAX messenger client, sandboxed with Firejail'
summary_ru='Клиент мессенджера MAX в песочнице Firejail'
group='Networking/Instant messaging'
desc='MAX is the Russian state-affiliated instant messaging client. This package always launches it inside a Firejail sandbox that hides the rest of the home directory and blocks the standalone crash-report uploader, since the app has no independent security track record and no reason to see the whole system.'
desc_ru='MAX — российский государственно-аффилированный клиент мгновенных сообщений. Пакет всегда запускает его в песочнице Firejail, которая скрывает остальной домашний каталог и блокирует отдельный процесс отправки крэш-дампов — у приложения нет независимой истории аудита безопасности и нет причин видеть всю систему.'
homepage='https://max.ru/'
maintainer='max.ru <https://max.ru/>'
architectures=('amd64')
license=('Custom')
nonfree=1
nonfree_msg='MAX является проприетарным приложением. Использование мессенджера, учетной записи и сетевых функций регулируется условиями MAX.'
nonfree_url='https://legal.max.ru/ps'
provides=()
replaces=('max')
conflicts=()
auto_reqprov_method="dirty"
auto_req=0
auto_prov=0
deps=('firejail')
deps_debian=('firejail' 'libxcb-xinerama0' 'libxcb-composite0' 'libxcb-ewmh2' 'libva-x11-2' 'libva-drm2' 'libvdpau1' 'libnotify4' 'libxcb-dri2-0' 'libopengl0' 'libxcb-cursor0' 'libxkbcommon-x11-0' 'libxcb-icccm4' 'libxcb-keysyms1' 'libxss1' 'libglib2.0-0' 'gsettings-desktop-schemas' 'ca-certificates')
deps_ubuntu=("${deps_debian[@]}")
deps_fedora=('firejail' 'libxcb' 'libva' 'libvdpau' 'libnotify' 'libglvnd-opengl' 'xcb-util-cursor' 'libxkbcommon-x11' 'xcb-util-wm' 'xcb-util-keysyms' 'libXScrnSaver' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
deps_arch=('firejail' 'libxcb' 'libva' 'libvdpau' 'libnotify' 'libglvnd' 'xcb-util-cursor' 'libxkbcommon-x11' 'xcb-util-wm' 'xcb-util-keysyms' 'libxss' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
deps_opensuse=('firejail' 'libxcb1' 'libva2' 'libvdpau1' 'libnotify4' 'libxcb-cursor0' 'libxkbcommon-x11-0' 'xcb-util-wm0' 'xcb-util-keysyms0' 'libXss1' 'libglib-2_0-0' 'gsettings-desktop-schemas' 'ca-certificates')
deps_altlinux=('firejail' 'libxcb' 'libxcbutil-cursor' 'libxcbutil-icccm' 'libxcbutil-keysyms' 'libXScrnSaver' 'libva' 'libvdpau' 'libnotify' 'libOpenGL' 'libxkbcommon-x11' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
opt_deps=()
opt_deps_debian=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
opt_deps_ubuntu=("${opt_deps_debian[@]}")
opt_deps_fedora=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
opt_deps_arch=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
opt_deps_opensuse=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
opt_deps_altlinux=('desktop-file-utils' 'icon-theme-hicolor' 'pipewire')
build_deps=('binutils')
sources=(
"https://download.max.ru/linux/deb/pool/main/m/max/MAX-26.24.0.75261.deb?~archive=false&~name=max.deb"
'local:///max.desktop'
'local:///max.profile'
'local:///LICENSE'
)
checksums=(
'sha256:7151aa2559e5fe22dd4dd6cf037b5d5cd38d302f84e49d4c4be94e1c4fe1f7d5'
'sha256:80ec5c0f4777ab00c433c25ffa70ef23d1752785e6584288d189518b8b43d613'
'sha256:cf8c986f7f1a9841be33b43cfd8e34e6c75dac6ffea07aad07869177fc7768c7'
'sha256:ddfcad273084c8b5690f6276fb29d8990ff4a7114db8a89b3f46255f8675e6b6'
)
scripts=(
['postinstall']='postinstall.sh'
['postremove']='postremove.sh'
)
package() {
cd "${srcdir}"
mkdir -p "${srcdir}/extracted"
ar x max.deb
tar -xf data.tar.* -C "${srcdir}/extracted"
install -dm755 "${pkgdir}/usr/share"
cp -a "${srcdir}/extracted/usr/share/max" "${pkgdir}/usr/share/max"
install -Dm644 "${srcdir}/extracted/usr/share/pixmaps/max.png" \
"${pkgdir}/usr/share/pixmaps/max.png"
for icon in "${srcdir}"/extracted/usr/share/icons/hicolor/*/apps/max.png; do
size="$(basename "$(dirname "$(dirname "$icon")")")"
install -Dm644 "$icon" \
"${pkgdir}/usr/share/icons/hicolor/${size}/apps/max.png"
done
install -Dm644 max.profile "${pkgdir}/etc/firejail/max.profile"
# The desktop file and every other launch path go through this wrapper —
# MAX never runs unsandboxed regardless of how it's started.
install -Dm755 /dev/stdin "${pkgdir}/usr/bin/max" <<'EOF'
#!/bin/sh
exec firejail --profile=max -- /usr/share/max/bin/max "$@"
EOF
install -Dm644 max.desktop "${pkgdir}/usr/share/applications/max.desktop"
install-license "${srcdir}/LICENSE" "max/LICENSE.nivora"
}
files() {
files-find-binary
files-find-desktop
files-find-license
files-find \
"/etc/firejail/max.profile" \
"/usr/share/max/**/*" \
"/usr/share/pixmaps/max.png" \
"/usr/share/icons/hicolor/*/apps/max.png"
}
+16
View File
@@ -0,0 +1,16 @@
[Desktop Entry]
Type=Application
Terminal=false
Name=MAX
Exec=/usr/bin/max %U
Icon=max
MimeType=x-scheme-handler/max;
Comment=MAX Messenger Client Application
Comment[ru]=Клиентское приложение мессенджера MAX
StartupWMClass=max
Categories=Chat;Network;InstantMessaging;Qt;
Keywords=max;chat;im;messaging;messenger;sms;
DBusActivatable=false
SingleMainWindow=true
X-GNOME-UsesNotifications=true
X-GNOME-SingleWindow=true
+53
View File
@@ -0,0 +1,53 @@
# Firejail profile for MAX Messenger (Nivora package)
# MAX is a proprietary Russian messenger; this profile keeps it away from
# the rest of the user's files and system, and blocks its standalone
# crash-report uploader.
include max.local
include globals.local
noblacklist ${HOME}/.config/max
noblacklist ${HOME}/.cache/max
noblacklist ${HOME}/.local/share/max
include disable-common.inc
include disable-devel.inc
include disable-exec.inc
include disable-interpreters.inc
include disable-programs.inc
include landlock-common.inc
mkdir ${HOME}/.config/max
mkdir ${HOME}/.cache/max
mkdir ${HOME}/.local/share/max
whitelist ${HOME}/.config/max
whitelist ${HOME}/.cache/max
whitelist ${HOME}/.local/share/max
include whitelist-common.inc
include whitelist-run-common.inc
include whitelist-usr-share-common.inc
include whitelist-var-common.inc
caps.drop all
netfilter
nodvd
nogroups
nonewprivs
noroot
notv
nou2f
protocol unix,inet,inet6
seccomp
restrict-namespaces
disable-mnt
private-dev
private-tmp
# Chromium/Qt-style standalone crash uploader: no messaging function, only
# phones home with crash dumps. Block it outright rather than trust a
# network-level filter.
blacklist /usr/share/max/bin/crashpad_handler
blacklist /usr/share/max/bin/max-service/bin/crashpad_handler
dbus-system none
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
set -euo pipefail
optional_refresh() {
local label=$1
shift
if ! "$@"; then
echo "Предупреждение: не удалось обновить ${label}." >&2
fi
}
if command -v update-desktop-database >/dev/null 2>&1; then
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
fi
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
fi
if command -v kbuildsycoca6 >/dev/null 2>&1; then
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
fi
if ! command -v firejail >/dev/null 2>&1; then
echo "Предупреждение: firejail не найден в PATH — MAX запускается только через firejail, пакет firejail должен быть установлен." >&2
fi
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
set -euo pipefail
optional_refresh() {
local label=$1
shift
if ! "$@"; then
echo "Предупреждение: не удалось обновить ${label}." >&2
fi
}
if command -v update-desktop-database >/dev/null 2>&1; then
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
fi
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
fi
if command -v kbuildsycoca6 >/dev/null 2>&1; then
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
fi
+1
View File
@@ -0,0 +1 @@
include = "../stapler-repo.toml"