Agent Wranglers

DSK-40Recommended

Ask the Linux sandbox for the fewest permissions

Ship Flatpak and Snap packages with sandbox permissions limited to what the app uses. Use portals or interfaces for files and devices, and never grant the whole home folder, the whole file system or full session bus access.

How to do it

A Flatpak or a strictly confined Snap reaches only what its manifest grants. Flatpak's documentation says permanent file access should be as small as possible, and recommends XDG folders and portals instead of --filesystem=home or --filesystem=host. It warns that full session or system bus access is a security risk that only development tools need. A file chooser portal hands the app the one file the user picked. Snap grants access through interfaces declared as plugs. Classic confinement removes the sandbox and needs a manual store review. Some interfaces, such as home, connect without review, so declare them only when the app reads the home folder. Flathub and the Snap Store sign the packages, as sign Linux packages and the repository that serves them notes.

Examples

YAML example

# com.example.Ledgerly.yml: files through the portal, network, display, no home folder
finish-args:
  - --share=network
  - --socket=wayland
  - --socket=fallback-x11
  - --filesystem=xdg-documents/Ledgerly:create

Python example

# check_sandbox.py: run in CI on the Flatpak manifest
import sys, yaml

FORBIDDEN = {"--filesystem=home", "--filesystem=host", "--socket=session-bus", "--socket=system-bus"}

finish_args = set(yaml.safe_load(open(sys.argv[1]))["finish-args"])
if finish_args & FORBIDDEN:
    sys.exit(f"broad sandbox permission: {sorted(finish_args & FORBIDDEN)}")

JavaScript example

// check-snap.mjs: run in CI on snapcraft.yaml
import { readFileSync } from 'node:fs';
import { parse } from 'yaml';

const APPROVED_PLUGS = new Set(['network', 'wayland', 'x11', 'desktop']);
const snap = parse(readFileSync('snap/snapcraft.yaml', 'utf8'));
const plugs = Object.values(snap.apps).flatMap(app => app.plugs ?? []);
const unapproved = plugs.filter(plug => !APPROVED_PLUGS.has(plug));
if (snap.confinement !== 'strict' || unapproved.length) throw new Error(`sandbox too wide: ${snap.confinement} ${unapproved}`);

How to check

A CI step reads the Flatpak manifest and fails on --filesystem=home, --filesystem=host, --socket=session-bus or --socket=system-bus. It reads snapcraft.yaml and fails on confinement: classic or on a plug not in the approved list.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/installs-and-local-privileges/linux-sandbox-permissions">Agent Wranglers desktop apps and extensions playbook</a>. In code you write, add a comment next to it with the same link.