Inspect snap-confine Without Breaking Snap Security

A snap fails to launch with a cryptic error, and snap-confine is usually where the trail goes cold. This guide identifies the installed snap-confine build, shows which confinement artefacts it expects, and diagnoses a failed launch without editing AppArmor, seccomp or mount policy. Allow about 15 minutes. You need a shell and the installed snapd package. Most checks are unprivileged; reading some package state or service logs may require sudo.

Safety boundary: snap-confine is an internal snapd helper, not a general-purpose sandbox command. Do not use it to launch an arbitrary host program, do not replace its profiles with permissive ones, and do not delete files under /var/lib/snapd or /run/snapd/ns while snaps are running.

1. Confirm the local version and executable

The installed manual page on this system describes snapd 2.28, but the package installed here is newer. That difference matters: the older page documents optional --classic and --base arguments, while the current binary's direct usage output accepts a security tag and executable. Start with facts from this host.

$ dpkg-query -W -f='${Package} ${Version}\n' snapd
snapd 2.76.3+ubuntu24.04
$ command -v snap-confine
$ ls -l /usr/lib/snapd/snap-confine
$ /usr/lib/snapd/snap-confine 2>&1
Usage: snap-confine <security-tag> <executable>

application or hook security tag was not provided

The path from command -v can be empty because this internal helper is not normally on a user's PATH. The packaged executable is commonly under /usr/lib/snapd. The non-zero result from an invocation with no arguments is expected and proves only that argument validation ran.

Checkpoint: Record the package version and the executable path before comparing a report with another machine. Do not treat the 2017 manual page's interface as a guarantee for snapd 2.76.3.

2. Launch snaps through snapd

For normal operation, use the public snap command and let snapd construct the security tag, base and environment. For example, replace SNAP_NAME with a snap and application that are installed on this host:

$ snap list SNAP_NAME
$ snap run SNAP_NAME

The second command may start a real application, so choose a harmless installed snap when testing. If you only want to inspect metadata, stop after snap list. Running a graphical or networked application can have side effects belonging to that application; snap-confine itself is not a dry-run facility.

Do not copy a guessed security tag into a hand-written snap-confine command. A direct call without the environment and policy prepared by snapd commonly fails before the target program starts. On this host, even a syntactically complete test stops with a missing SNAP_INSTANCE_NAME value:

$ /usr/lib/snapd/snap-confine demo-tag /usr/bin/true 2>&1
SNAP_INSTANCE_NAME is not set

That is a diagnostic boundary, not a recipe for setting the variable yourself. The variable, profile and mount state belong to snapd's launch path.

3. Check the three confinement inputs

snap-confine prepares a process environment using several kernel-enforced controls. Inspect the files without changing them:

$ sudo find /var/lib/snapd/seccomp/bpf -maxdepth 1 -type f -printf '%f\n' 2>/dev/null | sort | head
$ sudo find /var/lib/snapd/mount -maxdepth 1 -type f -name 'snap.*.fstab' -printf '%f\n' 2>/dev/null | sort | head
$ sudo ls -la /run/snapd/ns/

The first directory contains compiled seccomp BPF files and may also contain source files. The file name is derived from a security tag, so an arbitrary name in a command will not identify a useful profile. A mount profile, when present, is named snap.SNAP_NAME.fstab. Its directives are applied in order and a failed directive aborts the setup. The namespace directory contains locks and, for preserved namespaces, mount-namespace handles.

AppArmor is separate from these files. snap-confine switches to a mandatory profile already loaded in the kernel. Check the service's view of AppArmor if the utility is installed:

$ sudo aa-status --profiled

An empty result, a missing utility or a permission error is evidence to investigate, not a reason to disable AppArmor. The profile is managed by snapd and its exact name is host-specific.

Checkpoint: You should now know whether the failure is before policy lookup, in AppArmor, in seccomp profile loading, or in mount-namespace setup. Do not edit any of the inspected files during this check.

4. Turn on temporary diagnostics

Set SNAP_CONFINE_DEBUG only for the one launch you are investigating. The manpage says its additional diagnostics go to standard error. Keep the command scoped to a harmless installed snap or to a normal launch you are already authorised to test:

$ SNAP_CONFINE_DEBUG=1 snap run SNAP_NAME 2> snap-confine-debug.log
$ status=$?
$ printf 'snap run status: %s\n' "$status"
$ sed -n '1,120p' snap-confine-debug.log

This can start the snap, and the log may contain paths or security-tag details. Treat it as operational data and remove it when no longer needed:

$ rm -- snap-confine-debug.log

Removing this temporary log is safe once you have recorded the relevant error. Do not set the testing-only variables documented by the old page, such as SNAPPY_LAUNCHER_INSIDE_TESTS or SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR, on a production launch. The manual explicitly says they are internal and not to be relied upon.

5. Read failures without weakening policy

Use the first meaningful error in the launch output. A missing AppArmor profile means the required kernel policy is not available. A missing /var/lib/snapd/seccomp/bpf/<security-tag>.bin means the compiled seccomp program cannot be loaded. A mount error points to the snap's mount profile or to a namespace operation. These are configuration or host-state problems, not prompts to make the profile permissive.

Check snapd's service state and recent journal entries as separate, read-only steps:

$ systemctl is-active snapd.service
$ sudo journalctl -u snapd.service -n 80 --no-pager

If the service is inactive, use your normal service-maintenance process and check why it stopped before attempting a restart. A restart is service-disrupting and is not included here. If only one snap fails, compare its name and revision with the profile and mount filenames rather than removing shared namespace state.

6. Understand the security model

AppArmor mediates more than file reads. Its profile can constrain system calls, paths, capabilities and D-Bus access. Seccomp supplies a compiled BPF program; the documented safety behaviour is that a disallowed system call can cause the application executable to be killed by the kernel. The mount profile builds a per-snap view of the filesystem. Mount entries start with bind, read-only, nodev and nosuid flags unless an option reverses one of them, and the documented helper supports bind mounts.

Applications from the same snap share a mount namespace, while different snaps use separate namespaces. That explains why inspecting /run/snapd/ns can show state that outlives one application process. It is managed runtime state, not a directory to clean up manually.

The older manual page says the base defaults to core when omitted. Current snapd chooses launch metadata itself, and the installed binary does not advertise the old optional switches in its direct usage output. Prefer snapd's public command and the installed package's behaviour when the two descriptions differ.

Done means