Features define what a sandbox permits

Every feature of the sandbox, one row each, grouped by what it opens or closes. Each row says what the feature lets through and what it refuses, and a test of a row shows both. A row's name, in the last column, stays the feature's for life, so a test can name the row it proves. Where is both for Linux and macOS alike. How each works and what it guarantees is in Security; every key of a spec, in the spec.

Files

What a sandbox reads and writes of your files. Agents' folders are hidden to every sandbox, Link's settings, ~/.lnk, are closed read or written, and a grant reached through a link is named by its real path. A project's dot files are .git, .envrc, .vscode, .idea and hook managers' files. A short /etc keeps what programs read to load, find users and names, and check certificates, refusing shadow, SSH's host keys, anything named private, and writing any of it.

FeatureLets throughRefusesKey, flagWhereRow
Closed by defaultThe system's programs and libraries, read onlyEvery folder of yours no grant names, your home among themnonebothfiles.closed
Folder it writesReading and writing in the folder, and below itWriting beside it, in another folder of your home[files] write, --writebothfiles.write
Folder it readsReading in the folderWriting in it[files] read, --readbothfiles.read
Your whole home, readReading every folder of your homeLink's settings, agents' folders, writingread = ["~"], --read '~'bothfiles.home
Folder hiddenThe write and read folders inside itEverything else in it, even under --read '~'[files] hide, --hidebothfiles.hide
Agents' folders hiddenA folder in them that flags name, as its harness has~/Link/Agents, ~/Link/History; a spec naming themnonebothfiles.agents
Link's settings closedlnk-sandbox itself, read by its file alone~/.lnk; a grant in it, a write holding itnonebothfiles.settings
Project's dot files read onlyReading them at the top of a folder it writesWriting, renaming or removing themnonebothfiles.dot
Project's dot files writtenWriting them in a folder of write it namesNaming a folder that isn't in write[files] write_dot_files, --write-dot-filesbothfiles.dot-write
No grant through a linkA link root owns, such as the system's ownA grant through a link another user ownsnonebothfiles.links
Temporary folders of its own/tmp, /var/tmp and /dev/shm, empty and its ownSeeing what another program left therenoneLinuxfiles.tmp
Short /etcWhat programs read to load, name users and check TLSshadow, SSH's host keys, private, any writenoneLinuxfiles.etc
Descriptors closedstdin, stdout and stderrEvery other descriptor what started the sandbox left opennoneLinuxfiles.descriptors

Programs

Which programs it may run: with no spec, any the files grant; with one, those its [commands] lists, and never one it could write.

FeatureLets throughRefusesKey, flagWhereRow
Any program, without a specEvery program the files grantNothing morenonebothprograms.any
Programs it may runThe programs, paths and folders it listsEvery other, with "Permission denied", named by the sandbox[commands] allow, --commandbothprograms.allow
Spec without [commands]NothingEvery program, the one run starts too, before it startsnonebothprograms.none
Every programAny programNothing, but the files and network still holdallow = ["*"]bothprograms.star
No program it can writeA program in a folder it only readsAn entry in a folder it writes, or in /tmp[commands] allowbothprograms.writable
No code run from a descriptorRunning a file by its pathexecveat of a descriptor, a memory file made executablenoneLinuxprograms.descriptor
Learning a command's programsRunning every program once, under the other grantsWriting anything: it prints the entrieslnk sandbox learnbothprograms.learn
Xcode's programsReading the developer toolsWriting themdeveloper_tools, --developer-toolsmacOSprograms.developer-tools

Network

How it reaches the network at all. A cleared environment refuses every other variable of your shell, tokens and SSH_AUTH_SOCK among them; where its traffic leaves is direct, a SOCKS5 proxy, or an HTTP proxy on this machine's loopback.

FeatureLets throughRefusesKey, flagWhereRow
No networkNothingEvery host, port and name, inside and outnonebothnetwork.none
Through Link's proxyWhat the proxy's sections allow, at HTTPS_PROXYA program that ignores HTTPS_PROXY: it has no networkmode = "proxy", the defaultbothnetwork.proxy
Network as it isAny host and port, unfiltered and unloggedThe sections a proxy carries, beside it, in a specmode = "host", --network-mode hostbothnetwork.host
Where its traffic leavesdirect, SOCKS5, or an HTTP proxy on this loopbackA Unix socket another user serves, a link in its place--upstreambothnetwork.upstream
Cleared environmentPATH, HOME, TERM, the locale and who you areYour shell's other variables, SSH_AUTH_SOCK toononebothnetwork.environment

Internet

Public hosts, through the proxy. Never this machine or its network refuses loopback, private, link-local and metadata addresses however written, and a name resolving there. Named endpoints refuse an endpoint whose host isn't allowed, and DNS answers the names its hosts allow, and its endpoints' names at addresses of its own.

FeatureLets throughRefusesKey, flagWhereRow
Hosts it may reachThe hosts listed, over CONNECT and http://Any other host, by name, with a 403 and no lookup[internet] hosts, --internet-hostbothinternet.hosts
Any public hostEvery public hostThis machine, your network, a cloud's metadata servicehosts = ["*"]bothinternet.any
Names under a name*.example.com's namesexample.com itselfhosts = ["*.example.com"]bothinternet.wildcard
Never this machine or its networkPublic addressesLoopback, private, link-local and metadata addressesnonebothinternet.private
HTTPS and HTTP onlyCONNECT to 443, http:// to 80Any other port no endpoint namesnonebothinternet.ports
Named endpointsA host:port its hosts allow, through the proxyA port no endpoint names; a host not allowed[internet] tcp, --tcpbothinternet.tcp
DNS for named endpointsIts hosts' names, its endpoints' at addresses of its ownEvery other name, before anything is asked[internet] tcpLinuxinternet.dns
Calls a minuteThat many calls a minuteThe rest, with a 429[internet] per_minute, --per-minutebothinternet.per-minute
One host a tunnelA TLS tunnel asking for the host checkedA tunnel whose ClientHello names another hostnonebothinternet.sni

Your network and this machine

Machines of your network refuse this machine, its containers, link-local and metadata addresses, and any public address. A local model refuses pulling, creating, copying, pushing or deleting a model, with a 403.

FeatureLets throughRefusesKey, flagWhereRow
Machines of your networkThe names, addresses and ranges listed, on any portThis machine, its containers, link-local, metadata, public[lan] hosts, --lan-hostbothlan.hosts
Cloud's network kept outExact addresses* or a range holding a private block, on a cloud's machine[lan] hostsbothlan.cloud
This machine's ports closedNothingEvery port of this machine's loopbacknonebothlocalhost.closed
Ports it may callThe ports listed, the service's whole APIEvery other port; 40781; "*" behind a proxy[localhost] ports, --portbothlocalhost.ports
Local model, inference onlyChat, generation, embeddings and the models' listPulling, making, copying, pushing or deleting, 403[localhost] models, --modelbothlocalhost.models

Routes

Ways out served outside the sandbox. A hosted model's key refuses a request without the placeholder, a provider's server-side tools and a URL to fetch. No web page reaches the proxy: a request to the proxy itself from a page, with another Host, Origin or Sec-Fetch-Site, is refused.

FeatureLets throughRefusesKey, flagWhereRow
Hosted model's key, added outsideInference with the placeholder the run was givenNo placeholder; server-side tools; a URL to fetchan agent's keys on the wirebothroutes.model
Service's secret, added outsideThe rule's paths with the placeholderThe rule's refused paths; any other hostan agent's secretsbothroutes.secret
Routes behind a secretA call carrying the proxy's URL secretA call without it, to a tool, a local model or opennonebothroutes.url-secret
No web page reaches the proxyCONNECT and http:// requestsA page's request to the proxy itselfnonebothroutes.web-page

Tools and pages

Tools that run outside, the questions they ask you, and pages it may open, which refuse another host or scheme, an app, a file, this machine or its network.

FeatureLets throughRefusesKey, flagWhereRow
Tools it may callThe tools listed, at $LNK_TOOL_<NAME>Every other tool[tools] names, --toolbothtools.named
Calls that don't askThe calls the tool's --allow namesEvery other call, asked, refused with no one to asklnk sandbox tool add --allowbothtools.allow
Tool taken awayNothing once removedThe next call of a running sessionlnk sandbox tool removebothtools.remove
One server for every sandboxEach session its own answersOne session's answers to anotherlnk sandbox tool add --sharedbothtools.shared
Answering a questionlnk sandbox answer yes, onceNo, two minutes of silence, a second answerlnk sandbox asksbothasks.answer
Pages it may openAn https:// page on a host listed, asked firstAnother host or scheme, an app, a file, this machine[browser] hosts, --browser-hostbothbrowser.hosts

The wire

What the proxy logs and counts, and how its wire is stopped or paused. A wire pauses itself after 30 refusals a minute, 20 targets, or a call to a metadata service.

FeatureLets throughRefusesKey, flagWhereRow
Every call loggedA line a call: when, the sandbox, verb, host, outcomeA path, a header or a bodylnk sandbox logbothwire.log
Refusals loggedrefused lines, alone with --refusedOther outcomes, with --refusedlnk sandbox log --refusedbothwire.refused
Bytes each wayEach running proxy's countsNothinglnk sandbox trafficbothwire.traffic
Kill switchNothing while it's on; --off opens the wires againEvery call of every proxy, open ones within a secondlnk sandbox stopbothwire.stop
One wire pausedEvery call once resumedEvery call of that sandbox's proxylnk sandbox pause, resumebothwire.pause
Wire pausing itselfNormal workCalls past 30 refusals a minute, 20 targets, metadatanonebothwire.auto-pause

Specs and checks

A spec file can't open Link's settings, a dot folder of your home, PATH, the system's folders, the spec's own folder, sockets' folders, or ... One shape refuses an unknown key, an empty section, "*" beside other entries, and a file over 64 KiB.

FeatureLets throughRefusesKey, flagWhereRow
Spec from its grantsA spec of the flags given, printedNothinglnk sandbox specbothspec.write
New spec asks firstA spec run here before; --yesA new or changed spec with no terminal and no --yeslnk sandbox run --specbothspec.asks
What a file can't openA grant of a folder of your ownWhat a file can't open (which)--specbothspec.refused
One shape, checkedEvery key the table namesAn unknown key, an empty section, a file too biglnk sandbox spec --keysbothspec.schema
Flags over a fileA flag's key in place of the file's; --hide addedNothing moreflags beside --specbothspec.flags
One OS's tableThe table of the OS it runs onThe other OS's table[<section>.linux], [<section>.macos]bothspec.os
Sandbox tried from insideblocked, allowed and open rowsA leaked row, which exits 1lnk sandbox checkbothcheck.probes
Ready to run hereExit 0 where it canWhat's missing, saidlnk sandbox readybothcheck.ready
Session over SSHA shell or command in the spec's sandbox, its folder writtenA spec whose [commands] doesn't run /bin/bashlnk sandbox enterLinuxenter.session

Its permissions

lnk sandbox permissions lists each section of a spec and its flags, and lnk sandbox run --help describes each flag. An agent's grants, which lnk agent allow and deny change, are each a key of these rows: Permissions.