SCUA

News

Permissions in a file

August 21, 2026

A sandboxed run used to mean a row of flags:

scua --allow-fs=./data --allow-net=api.internal,cdn.example --allow-env=PORT,HOME \
     --allow-serve=127.0.0.1:8080 app.scua

Long enough to copy between shells and get wrong, and the policy it encodes is written down nowhere. It can be a file now:

# permissions.toml
[capabilities]
fs = "./data"
net = ["api.internal", "cdn.example"]
env = ["PORT", "HOME"]
serve = "127.0.0.1:8080"
scua --allow-file=permissions.toml app.scua

The keys are the flag names, so there is nothing new to learn. true means the bare flag, a string or a list is the constrained form, and false or an empty list refuses the capability. A refusal sticks, which is what makes "everything except one thing" a single readable command:

scua --allow-all --allow-file=no-net.toml app.scua

--allow-all is the other half of this. It grants every capability in its broadest form, for a script you already trust, and a narrower flag still wins no matter which order you write the two in.

An unknown key stops the run rather than warning. A typo like nett would otherwise grant nothing at all, silently, and you would find out much later when the script died on a name that did not exist, with the policy file still looking right.

There was a version of this that did not ship, and it is the more useful half of the story. A [capabilities] table in a project's own scua.toml would have applied with no flag at all, which is the checked-in, reviewed-in-a-diff form people have asked for. A review of it found three ways through. The one with no available answer is that a script holding nothing but --allow-fs can write scua.toml into its own granted root, and then the next run of anything in that directory holds every capability. The granted filesystem root and the discovered manifest are the same directory in every layout we recommend. A sandbox whose authority depends on its own writable state is not a sandbox, so that source came out and grants stay on the command line. A checked-in policy still works. It costs one flag rather than none.