Security policies

Without custom flags at installation, or subsequent interface connections, snaps remain confined to a restrictive security sandbox, preventing access to system resources outside the snap.

Snap developers need to be aware which system resources their applications depend on from within the snap.

Security policies and store policies work together to allow developers to quickly confine and update their applications to provide safety to end users. This document provides an overview of core mechanisms that underpins the secure snap sandbox as well as information on how to configure and work with the security policies for snaps you publish.

For more general details on what confinement entails, see Snap confinement, and see below for implementation details.

Security overview

Application developers should not need to know about, or understand, the low-level implementation details of how a security policy is enforced.

Each command declared with the apps snap metadata is tracked by the system assigning a security label to the command.

This security label takes the form of snap.<snap>.<app> where <snap> is the name of the snap, and <app> is the application name.

For example, the following is an app declaration from snap.yaml:

name: foo
version: 1.0
apps:
  bar:
    command: bar
  baz:
    command: baz
    daemon: simple
    plugs: [network]
  • the security label for bar is snap.foo.bar . It uses only the default policy.

  • the security label for baz is snap.foo.baz . It uses the default policy plus the network interface security policy as provided by the core snap.

This security label is used throughout the system, including during the process confinement phase when running the application.

Under the hood, the application runner does the following:

  1. Sets up various environment variables:

    • HOME: set to SNAP_USER_DATA for all commands

    • SNAP: read-only install directory

    • SNAP_ARCH: the architecture of device (eg, amd64, arm64, armhf, i386, etc)

    • SNAP_DATA: writable area for a particular revision of the snap

    • SNAP_COMMON: writable area common across all revisions of the snap

    • SNAP_LIBRARY_PATH: additional directories which should be added to LD_LIBRARY_PATH

    • SNAP_NAME: snap name

    • SNAP_INSTANCE_NAME: snap instance name incl. instance key if one is set (snapd 2.36+)

    • SNAP_INSTANCE_KEY: instance key if any (snapd 2.36+)

    • SNAP_REVISION: store revision of the snap

    • SNAP_USER_DATA: per-user writable area for a particular revision of the snap

    • SNAP_USER_COMMON: per-user writable area common across all revisions of the snap

    • SNAP_VERSION: snap version (from snap.yaml)

  2. When hardware is assigned to the snap, a device cgroup is set up with default devices (eg, /dev/null, /dev/urandom, etc) and any devices that are assigned to this snap. Hardware is assigned with interface connections.

  3. Sets up a private mount namespace shared across all the commands in the snap.

  4. Sets up a private /tmp directory using a per-snap private mount namespace and mounting a per-snap directory on /tmp.

  5. Sets up a new instance of devpts per command.

  6. Sets up the seccomp filter for the command.

  7. Executes the command under the command-specific AppArmor profile under a default nice value.

Security building blocks

Cryptography

The snap packaging system employs various cryptographic technologies to secure local and remote snap operations.

Locally, these are handled by the snap daemon, snapd, while remote connections require mediation between snapd and the Snap Store, which supports its own set of cryptographic technologies. Both sets of these are listed below.

Snapd (snap daemon) cryptography

In the standard snapd, cryptographic functionality is provided by Go’s native cryptographic implementations from the Go standard library. These implementations may make use of architecture-specific optimizations (CPU instruction set extensions such as AES-NI or SHA) where available.

Snapd is also being developed in a FIPS variant - not yet generally available - in which cryptographic operations are provided by OpenSSL rather than Go’s native implementations. In this variant, OpenSSL may either be bundled with snapd or supplied by the host system, enabling integration with cryptographic modules validated under FIPS in environments that require FIPS compliance. For more information about FIPS see: Information about FIPS on Ubuntu 22.04.

In both variants, cryptographically secure randomness is sourced from the operating system via the Linux kernel’s randomness interfaces (for example getrandom(2)), which provide entropy to user-space cryptographic libraries.

Snap Store cryptography

  • Digital signatures for assertions
    The key ID of the signing key is encoded with SHA3-384, and the assertion is signed with either 4096-bit or 8192-bit RSA.

  • Hashing of artifacts
    The store generates many hashes of an uploaded artefact using SHA3-384, SHA256 and SHA512 to ensure the uniqueness and integrity of the artefact.

  • Macaroons for authorisation and authentication
    SHA256 HMAC and NaCL secretbox

  • Macaroons encryption of 3rd party caveats
    Salsa20 (NaCL secretbox)

  • Enterprise Store nonce signing
    Used as additional security for REST API access. RSA 4096-bit is used to sign and verify the nonce.

Confinement and isolation mechanisms

When a snap is installed, its metadata is examined and is used to derive AppArmor profiles, Seccomp filters and device cgroup rules, alongside traditional permissions. This combination provides strong application confinement and isolation.

AppArmor

AppArmor profiles are generated for each command. These have the appropriate security label and command-specific AppArmor rules to mediate file access, application execution, Linux capabilities, mount, ptrace, IPC, signals, coarse-grained networking.

As already mentioned, each command runs under an app-specific default policy that may be extended through declared interfaces which are expressed in the metadata as plugs and slots. AppArmor policy violations in strict mode snaps will be denied access, and typically have errno set to EACCES. The violation will typically be logged.

See AppArmor violations for help tracking AppArmor problems.

Seccomp

A seccomp filter is generated for each command in a snap to run under, enabling allowlist syscall filtering, which can then be extended through declared interfaces expressed in the metadata as plugs and slots.

Processes with seccomp policy violations will be denied access to the system call with errno set to EPERM (snapd releases prior to 2.32 receive SIGSYS) and the violation is logged.

See Seccomp violations for help tracking Seccomp problems.

Device cgroup

udev rules are generated for each command to tag devices so they may be added/removed to the command’s device cgroup. By default, however, no devices are tagged and the device cgroup is not used, with AppArmor used to mediate access.

As determined by snapd, a device cgroup may be used in addition to AppArmor when a dependent interface is declared, as expressed through plugs and slots in the metadata.

Processes accessing devices not in the snap-specific device cgroup will be denied access with errno set to EPERM. Access violations are not logged.

Traditional permissions

Traditional file permissions (owner, group, file ACLs and others) are also enforced with snaps.

Processes trying to access resources which the traditional file permissions do not allow are denied access with errno typically set to EACCES (see the man page for the operation for specifics). Access violations are not logged.

Security policy implementation

The snap daemon uses AppArmor and Seccomp to create a security policy that is linked to a specific snap revision. This governs what a snap can access on your system. AppArmor profiles and Seccomp filters are created for each command, and while AppArmor profiles can be changed and reloaded while a process is running, Seccomp filters cannot.

Interfaces

Interfaces are implemented as plugs and slots. A plug in one snap may connect to a slot in another and this provides access to the resources required.

The snap connections command can be used to see available interfaces alongside their slots and plugs.

$ snap connections
Interface           Plug                                Slot               Notes
home                wormhole:home                       :home              -
log-observe         gnome-logs:log-observe              :log-observe       -
mount-observe       gnome-system-monitor:mount-observe  :mount-observe     -
[...]

In the above example output, the gnome-logs snap is connected to the log-observe interface, which means the security policy from log-observe has been added to gnome-logs.

Interfaces can be declared either per-snap or per-command:

  • if declared per-snap, all the commands within the snap have the interface security policy added to each command’s security policy when the interface is connected

  • if declared per-command, only the commands within the snap that declare use of the interface have the specified interface security policy added to them

An interface may either auto-connect upon install, or require the user to manually connect them. Interface connections and disconnections are performed via the snap connect and snap disconnect commands. See interfaces for details.

Policy switch during refresh

Snap security policy permits read and write access for the current revision, and read-only access for other revisions to preserve the capabilities of snap revert. More specifically, if 123 is the current revision, AppArmor policy is set to allow rw on SNAP_DATA=/var/snap/foo/123.

Before refresh awareness became available, if a refresh occurred while a snap was running, its AppArmor policy would be updated to allow w (write) on the new version and r (read) on the older versions, including the running version. The policy was applied immediately, which meant that write operations would start to fail for running processes.

Refresh awareness

By default, a service running from a snap needs to be restarted whenever the snap is refreshed (see Services and daemons for more details).

Stopping and starting a service is a requirement to support snap revert and its copying of a snap’s system data from the current version to the new version.

System data typically includes databases, data files, and configuration files (see Data locations), although all of this is up to the snap developer.

Reverting a snap with snap revert restores a snap’s system data to its prior state, and services accessing this data need to be stopped to protect the integrity of the data and also to facilitate changes to security policy that are required when a snap updates its system data location.

To help mitigate any potential issues when a restart is required, snapd will check for running processes associated with the snap before each refresh:

  • if no processes are running, the refresh is performed.

  • if systemd-initiated processes are detected, their associated units are first stopped, the snap refreshed, and those units started again.

  • if other snap-initiated processes are detected, refresh awareness is used to mediate the update.

Information security

Snapd includes the following built-in features that interacts with user information:

Snapd is designed to make these interactions secure by default. Developers are expected to implement their own data storage solutions, e.g. database and configuration files, on top of snapd’s secure mechanisms. This means developers share responsibility for ensuring the availability, integrity, confidentiality, and compatibility of user data over the lifetime of a snap or snap-based product.

Snaps that use classic confinement do not benefit from snapd’s sandboxing and isolation features, and thus operate with fewer security boundaries. This elevated level of access introduces a higher risk to the confidentiality and integrity of user data.

To mitigate this risk, snapd enforces an explicit acknowledgment from users by requiring the --classic flag at install time. Furthermore, to protect the ecosystem, only publishers who have passed a strict review and vetting process are permitted to publish classic snaps in the Snap Store.

How to establish strict confinement

The correct mindset is to request the minimum set of permissions necessary for a snap to function as currently required. When multiple interfaces provide overlapping permissions, choose the most restrictive one that still satisfies the requirements.

Avoid defining top-level plugs or slots that implicitly apply an interface to all apps and daemons in the snap. Instead, declare permissions as narrowly as possible.

These guidelines are considered during store approval of permission requests. Deviations from best practice will require a justification.

Sometimes it is also required to extend what is allowed by an existing interface or even to implement a new interface. When in doubt, feel free to consult the snapd team on the snapcraft forum.

To publish a classic snap that operates outside these restrictions, you must submit a classic confinement request that involves a rigorous process for vetting the publisher.

Security maintenance

Snapd is delivered both as Debian packages and as snaps, and the security maintenance responsibilities and lifecycles differ depending on the delivery mechanism.

The snapd Debian packages are maintained by the Ubuntu Security Team and receive security updates through the standard Ubuntu security maintenance process. The duration of this maintenance follows the Ubuntu Release Cycle. This lifecycle applies only to the snapd deb packages provided as part of Ubuntu releases.

The snapd snap is maintained by the snapd team, who are responsible for delivering security updates through snap revisions. The lifecycle and maintenance model for snapd snaps is separate from the Ubuntu release lifecycle and follows the Ubuntu Core and snap track maintenance model.

Ubuntu Core 16 includes snapd embedded within the core snap (which functions as the base operating system snap). Security maintenance for snapd in the Ubuntu Core 16 core snap is handled by the snapd team through updates to the core snap.

Security updates

The snapd team allocates capacity for security fixes following each major snapd release. Major snapd releases currently occur on an approximately two-month cadence, and a planned security update window is scheduled after each major release.

These security update releases are primarily intended to address high-priority security vulnerabilities that require timely remediation outside of the normal feature release cycle.

Lower-priority security vulnerabilities may be accumulated and delivered as part of these planned security update releases. Security updates may be released outside of this preferred cadence where required to address critical vulnerabilities.

Security vulnerabilities are handled under a responsible disclosure process. Security issues are tracked and developed privately and are not publicly visible until fixes are released and the vulnerability is disclosed. This ensures that users receive fixes before detailed vulnerability information becomes publicly available.

How to report vulnerabilities

Please report suspected security vulnerabilities privately by following the instructions in SECURITY.md.