SnapOS's defender is SnapGuard: ClamAV (services.clamav.daemon and
services.clamav.updater, enabled by the SnapOS module) wrapped by
snapguard (src/snapguard.c) with SnapOS policy.
An infected file is never deleted automatically. snapguard moves it to
quarantine and strips its exec bits, then the user decides. Quarantine lives in
~/.local/share/snapos/quarantine for a normal user and in
/var/lib/snapos/quarantine for root:
snapguard scan <path>... exit 0 clean, 1 infected, 2 could not scan
snapguard status engine, daemon, database, ACTIVE or LIMITED
snapguard quarantine <path> contain a file
snapguard restore <name> [--trust] put it back, optionally trust it
snapguard delete <name> delete it for good
snapguard list show the quarantine
snapguard open the window
snapguard trust <path> add its hash to the allowlist
- Allowlist: your own
~/.local/share/snapos/allow.txtplus the system-wide/etc/snapos/allow.txt(SHA-256 of files you trust). - Deny-list:
/etc/snapos/signatures.txt(SHA-256 of known-bad files, shipped with the system). - ClamAV. If the daemon is running,
clamdscan --fdpass(the daemon reads the file through a descriptor, so it needs no access to the user's folders). Otherwise oneclamscanrun for all the files of a scan, so the signature database is loaded once.
A file that could not be scanned is reported as such, never as clean.
snapguard status says whether the engine, the daemon and the virus database
are in place. The database downloads on the first boot with internet, and the
daemon retries by itself until it succeeds.
snapctl run <program> scans any undeclared program through snapguard
before it is drafted or run. snap-deb does the same for .deb files.
Programs from .deb files run inside a Debian layer (/var/lib/snapdeb,
src/snap-deb.c) through bubblewrap, with the user's home, display, sound,
devices and D-Bus sockets. The layer is a native layer, not a sandbox: a
program in it can do what it could do on a Debian computer, and installing a
.deb runs its maintainer scripts as root with every capability, as on
Debian. A package that brings a system service is installed too; the service
itself does not start inside the layer, and the user is told so. The one
protection is SnapGuard, which scans every .deb before it is declared: a
threat goes to quarantine and is never installed. The layer itself is created with Debian's
debootstrap against Debian's archive keys, which SnapOS ships in
/etc/snapos/debian-archive-keyring.gpg (from the debian-archive-keyring
package; without it no layer is created), and packages are
installed by Debian's apt from the official archive with security updates
enabled. Only root (through snapos rebuild or snap-deb sync) changes the
layer.
snapguard with no arguments opens the window (src/snapguard-gui.c, GTK3, installed
as snapguard-gui), a skin over the same commands: quick
scan of Downloads, scan a folder or a file, and a Quarantine tab with
Keep & trust and Delete. It calls snapguard scan, quarantine and the rest, so the rules are the
same. While it scans it shows each file as it is checked; when it finishes it
reports the files checked, the threats, the files that could not be checked and
the time taken, and sends a desktop notification.
snapguard-watch (src/snapguard-watch.c) starts at login and uses inotify
on ~/Downloads (and the folders inside it) and on /run/media/<user>. A
file is scanned when it is closed after writing or moved into place, so
browser downloads are checked once, when they are complete; temporary names
(.part, .crdownload) are ignored. A threat is contained with snapguard quarantine (or only reported when /etc/snapos/onInfected is warn) and a
desktop notification is sent. A drive that is plugged in is scanned whole.
Each scan runs in its own process, so a slow scan never delays the watching.
- Talking to
clamdover its socket protocol instead of runningclamdscan. - Sandboxing for programs that are not trusted yet.
snapos update (src/snapos.c) never replaces the running system. It checks
the machine and the release first, verifies the SHA-256 of the source package
against the checksum attached to the release (both come from the release
page over HTTPS, so this catches a corrupted download, not a compromised
release), builds the new NixOS generation with nixos-rebuild boot, and
leaves a marker in /var/lib/snapos/update. At boot snapos guard boot lets
a new generation start once; snapos guard approve removes the marker when a
user with uid ≥ 1000 has logged in, and after ten minutes without a login, or
on the next boot with the marker still there, switches the profile back to the
recorded generation, restores the previous /etc/snapos, and restarts. Only
root writes the markers; users only read them. Downloads go to
/var/lib/snapos/update/work, a folder only root can enter, never to /tmp.
- V1 and V1.1 (NixOS 24.11, Linux 6.6.94). The base stopped receiving security fixes on 30 June 2025; kernel vulnerabilities found since then, including local privilege escalations, are unpatched in those releases. Fixed by V2.0, which moves to NixOS 26.05 (Linux 6.18) and updates itself.
- V1.1 Debian layer.
snap-deb syncran a package's install scripts as root with all capabilities and without a pid namespace. V2.0 limited them to the capabilities dpkg needs. V2.5 went back to full powers on purpose: the layer is a native layer, like a Debian computer, and SnapGuard's scan of every.debis the protection. - Found and fixed during the V2.0 review, never released: the updater wrote
its downloads to
/tmpunder predictable names as root (a local user could plant a symbolic link there); file names reached desktop notifications as markup.
SnapOS aims to stop a user from running malware they downloaded or that came on removable media: an undeclared binary is scanned before it runs. It does not defend against a fully compromised root or against supply-chain attacks on the declared package set.