[supervisor]
Session limits, the seven syscall-coverage flags, how far workspace trust reaches, and DNS inspection.
Everything grith exec does at the syscall layer. The two sections most worth reading are
[supervisor.coverage] - which decides what is actually enforced -
and [supervisor.trust].
| Key | Default | What it does |
|---|---|---|
enabled | true | Turn supervision off. grith exec becomes a pass-through. |
default_profile | "generic" | Used when --profile is not passed. Blank is a fatal validation error. |
freeze_timeout_seconds | 300 | How long a held call waits for a reviewer before it is denied. |
deny_replay_seconds | 60 | How long a deny keeps auto-denying identical retries. 0 disables. |
approve_replay_seconds | 60 | How long an approval keeps auto-allowing identical retries. 0 disables. |
max_concurrent_sessions | 4 | Local cap on concurrent supervised sessions. |
pty_forwarding | true | Required for interactive agents. Off breaks agent TUIs. |
attach_mode | "traceme" | Linux attach mechanism. |
require_sandbox | false | Abort rather than supervise when the platform backend is degraded. |
pty_ownership_enforce | false | Deny writes to a /dev/pts that is not the tool's own terminal. Audit-only when off. |
enforce_authority_delegating_spawn | true | Escalate a spawn of docker, systemd-run, systemctl, at and similar. |
enforce_control_socket_connect | true | Escalate a connect to a control-injection socket - session D-Bus, tmux, screen, X11. |
dbus_message_inspection | true | Decide D-Bus per method call rather than per connection. |
authority_lost_terminate_after_seconds | 0 | Kill a session this long after the daemon stops accounting for it. 0 never does. |
⚠️The licence cap wins
max_concurrent_sessions only tightens. The daemon enforces the lower of this and the licence
entitlement - 2 on Community, 64 on a paid plan. A stock paid install still stops at 4 until you
raise this value.
attach_mode = "seize" is scaffolding: the spawn path refuses it. Leave it at traceme.
since 0.3.1 dbus_message_inspection is why a Chromium or Electron-based tool no
longer prompts on every D-Bus connect: the connect arms message inspection instead, and only the
method calls a curated allowlist does not vouch for escalate. Anything the supervisor cannot decode
escalates the whole connection, and tmux, screen and X11 keep connect-time escalation because there
is no per-message destination to decide on. No effect when enforce_control_socket_connect is off.
[supervisor.coverage]
Seven independent flags over the syscall categories added for staged rollout. This section is absent from the shipped config file - add it to change anything.
| Key | Default | Covers |
|---|---|---|
category1_hard_deny | true | Kernel module load/unload and kexec. Hard deny. |
category2_proxy | false | chown and the mount family, proxy-evaluated. |
category2_crossprocess | true | ptrace, process_vm_readv, process_vm_writev against a target outside the supervised tree. |
category3_namespace | false | unshare and setns. |
category4_arch_priv | true | sethostname, iopl, swapon, reboot and similar. Hard deny. |
deny_self_seccomp_notify | true | A tracee installing its own NEW_LISTENER seccomp filter. |
observe_self_seccomp_filter | false | Audit-only record of a tracee installing a plain seccomp filter. |
At defaults, chown, mount, unshare and setns are not enforced. A disabled
category falls through to the not-security-relevant branch and is allowed silently. Both are
off because sandboxes and rootless container runtimes do real mount, chown and namespace work,
so enabling them without calibrating the profile first produces prompts on legitimate
operations.
deny_self_seccomp_notify is the one to think twice about. It closes the proven escape that
out-ranks grith's own interception; its only known collateral is rootless container runtimes
that use seccomp-notify, which fail loudly rather than quietly.
Enable the two staged categories
[supervisor.coverage]
category2_proxy = true
category3_namespace = true[supervisor.trust]
How far a session's project trust reaches. Both widening keys are resolved once at session start and never re-read - a re-read would let the supervised tool grant itself more trust by creating directories.
| Key | Default | What it does |
|---|---|---|
include_linked_worktrees | true | Extend project trust to every git worktree of the launch repository. |
additional_project_roots | [] | Extra roots for layouts git cannot infer. |
restrict_to_workspace | false | Deny file operations outside the workspace instead of scoring them. |
${PROJECT_DIR} in a profile expands to the launch directory and nothing else, so without
include_linked_worktrees only the tree you started in is trusted. Because the listing
includes the main worktree, launching from repo/frontend/ trusts the repository root too.
git builds that list from files the supervised tool can write, so a reported worktree earns
trust only if it also sits inside the repository's enclosing directory, carries git's
back-pointer, and is not a credential directory. A repository checked out straight into your
home directory gets no linked-worktree trust at all - its enclosing directory would be the
whole of $HOME. Use additional_project_roots for that, and for a sibling checkout of a
different repository.
Trust is never literal: /, $HOME and any ancestor of it are refused however they are
declared, at most 32 roots are trusted per session, and credential directories inside a
trusted root still go to the proxy.
restrict_to_workspace turns the workspace into a boundary rather than a trusted region. It
is subtractive only - it never allows anything the filters would block. See
Workspace boundary, and
grith exec --workspace-only since 0.3.1 for the per-session form.
ℹ️Not settable from the CLI
Neither restrict_to_workspace nor additional_project_roots is on the grith config set
whitelist. Edit the file, or use grith exec --workspace-only per session.
[supervisor.dns_inspection]
| Key | Default | What it does |
|---|---|---|
enabled | true | Inspect DNS queries. |
observe_responses | true | Watch responses to build the exact IP-to-domain cache. |
block_tcp_dns | true | Deny TCP-DNS. It cannot be content-inspected, so allowing it would leave query blocking bypassable. |
upstream_resolver | unset | Override the resolver the proxy path forwards to. |
connected_udp_proxy | false | The connected-UDP proxy path. |
accept_proxy_network_authority | false | Explicit acceptance of the network authority proxy-owned sockets gain. |
proxy_queue_action | "refuse" | What a queue-range DNS decision does on the wire. forward is a compatibility mode. |
Eight proxy_* bounds (response size, three timeouts, four capacities) apply only when
connected_udp_proxy is on. grith config prints them all. Validation refuses
connected_udp_proxy without both enabled and accept_proxy_network_authority.
[supervisor.noise_reduction]
ignore_read_only (on) skips the pipeline for reads on an fd whose open was already scored.
batch_rapid_reads (on) coalesces rapid reads from the same fd into one pass per
batch_window_ms (50). Both are safe to leave on; restrict_to_workspace overrides
ignore_read_only for reads outside the workspace.
[supervisor.platform]
linux_mechanism and macos_mechanism are informational - nothing branches on either string.
seccomp_pre_filter is a dead knob from an earlier design; setting it does nothing. grith
runs on Linux x86_64 and Linux aarch64, using ptrace and seccomp-BPF together.