Sandbox Contract

link-sandbox-contract: the sandbox's policy, independent of its implementation. It reads a sandbox's spec, resolves its permissions, and checks addresses and names on the network, with no command line, backend or proxy, for every side that edits or enforces a policy.

The spec

Spec is a sandbox's spec, a TOML file whose sections are its only grants (Sandbox Spec): Files, Network (its NetworkMode), Internet, Lan, Localhost (its Port), Tools, Browser and Commands, each with an Os table. It's here, in its own contract, since more than the sandbox plugin keeps one: an agent's file, a harness's grants.

What it leaves to others

What a spec opens on a machine is the confinement resolver's, and its refusals that need the machine itself are the sandbox plugin's: another plugin has a spec checked by running lnk sandbox.

Its parts

spec::grants is the grant algebra policy editors share (union), spec::resolve the OS overrides and authored paths, and spec::schema the schema and documentation made from the type (Section), which lnk sandbox spec --keys and --schema print.

The programs a sandbox may run

Programs is Any ([commands] allow = ["*"]) or Only these, by path: a file, or a folder of them; none, nothing. Its requirement_policy names the effective command policy, unrestricted or restricted.

Folders every sandbox hides

hidden_dirs gives the folders every sandbox hides, whatever it's allowed, but for what it names in them: ~/Link/Agents (agents_dir, a folder per agent, hidden from every sandbox but an agent's own), ~/Link/Teams (teams_dir, hidden but for what a member is granted of it) and ~/Link/History (history_dir, what Link keeps a while of what's gone).

A folder no sandbox may write

unsafe_files says why no sandbox may write a folder, when it mustn't: where writing is a way out of a sandbox (programs and settings that run or are read outside it) or holds the user's keys.

Variables a caller can't give

check_given_variable refuses a variable a caller can't give a sandboxed program: those lnk sandbox run keeps or sets itself, the dynamic loader's (LD_*, DYLD_*) and a proxy's. Startup hooks and interpreter search paths are refused too: an environment grant must not install code before the requested command starts.

What Linux shows of the machine

system::LINUX_READS is what Linux's sandbox shows a program of the machine outside its own folders, read only, those that exist: the system's programs and libraries, and selected public settings from /etc. Anything kept in them, whatever its mode, a sandboxed program running as its owner can read; /run, /tmp and the homes it gives fresh.

A box's users

box_users is what the box plugin writes of a box's users (lnk box user) and every other side reads: where root keeps them, the line that lets a key in, and the one way into a user's sandbox, for an SSH session and a run alike.

Where root keeps them

In /etc/lnk/users/<name>/, where neither they nor anything they run writes: user.toml (BoxUser, their folder and key), <name>.toml (their sandbox's spec, its paths absolute) and authorized_keys, which sshd reads for them in place of their own, for the group lnk-users (GROUP).

The line that lets a key in

line gives it, restrict,pty,command="..." entering the sandbox: restrict turns off port, agent and X11 forwarding and ~/.ssh/rc, each a way around the sandbox, and pty gives back a terminal. Their login shell is /bin/sh, which reads no file of theirs before the command, and the programs are root's copies in /usr/local/lib/lnk.

Tests

LNK_TEST_BOX_ROOT (TEST_ROOT) puts a test's folder in place of /, for tests of a stand-in box; only a debug build reads it.

An ordinary box's workers

box_workers is the root launcher of an ordinary box: its settings in /etc/lnk/workers.json (CONFIG), ordinary with its Controller (uid, gid, groups) or packed, and the program it runs, /usr/local/lib/lnk/lnk-sandbox (PROGRAM). Packed boxes use their slot users; computers keep the person's explicit keeper fallback.

privileged

The root-owned helper: only an already authorized controller can ask sudo, and no sudo rule is given to a worker. It keeps explicitly inherited descriptors (the proxy's namespace handshake), and the child's given environment.