firma-run (root module)
Module: firma_run
Section titled “Module: firma_run”Contents
Section titled “Contents”Modules
authority- Authority selection and local-launch preparation.backendcapabilityconfigdns_stubegress_guard- Loopback egress guard: seccompuser-notifyinterceptor forconnect(2).erroridentitylog- Swappable foreground log sink shared with thefirmaCLI.proxy_bridgeroutingruntimeseccompsidecar
Module: authority
Section titled “Module: authority”Authority selection and local-launch preparation.
Subordinate modules:
- [
config] — user-levelfirma.tomlreader. - [
selection] — resolver that combines CLI args and config into a single [AuthoritySelection]. - [
prepare] — local Authority configuration and launch preparation. metadata— per-runauthority/metadata.tomlwriter.
Module: backend
Section titled “Module: backend”Module: capability
Section titled “Module: capability”Module: config
Section titled “Module: config”Module: dns_stub
Section titled “Module: dns_stub”Module: egress_guard
Section titled “Module: egress_guard”Loopback egress guard: seccomp user-notify interceptor for connect(2).
A wrapped agent’s direct connection to a loopback address bypasses
HTTP_PROXY and never reaches the Sidecar. To close that gap we trap every
connect(2) the agent makes and block the ones targeting a loopback address
that is not a sanctioned Firma endpoint (the proxy bridge or DNS stub).
A loopback destination is also allowed when the agent’s own network namespace
has a listener on that port — a service the agent started inside its jail
(e.g. a test server binding 127.0.0.1:0). Because the guard runs only in
structural mode, that namespace is private, so such a listener is by
construction in-jail and reachable only from the agent itself; the
netns_local_ports probe reads /proc/<pid>/net/* to recognize it.
Two-process design
Section titled “Two-process design”seccomp’s user-notify filter must be installed inside the sandbox, on
the agent’s own process, but serviced by a supervisor that is not itself
subject to the filter. bwrap offers no way to hand the notification
listener fd back to the parent, so:
- [
install_and_exec] runs as a thin wrapper inside the sandbox (invoked by the entrypoint asfirma __egress-guarded-run -- <agent> <args...>). It installs a filter that returnsSECCOMP_RET_USER_NOTIFforconnect, sends the resulting listener fd to the host supervisor over a Unix socket (SCM_RIGHTS), thenexecves the agent. The filter survives the exec. - [
start] runs the host-side supervisor (held in [crate::routing::NetworkRuntime]). It receives the listener fd and services notifications: it reads the targetsockaddrfrom the agent viaprocess_vm_readv(2), classifies it, and answers eachconnect.
Allow vs deny, and the TOCTOU caveat
Section titled “Allow vs deny, and the TOCTOU caveat”The deny path is race-free: returning an errno does not re-execute the
syscall. The allow path answers with SECCOMP_USER_NOTIF_FLAG_CONTINUE,
which re-reads the agent-controlled sockaddr when the kernel re-runs the
syscall — the classic seccomp-notify TOCTOU window. We accept it because the
allow-list is just Firma’s own loopback ports and, in structural mode, the
agent’s network namespace is private, so even a won race reaches only the
agent’s own loopback, never a host service. This is defense in depth layered
on the network-namespace boundary, not a standalone hard guarantee.
A related short-read hazard on the read path is also handled fail-closed:
process_vm_readv(2) can return fewer bytes than requested (e.g. a sockaddr
straddling a page boundary with the second page unmapped), which would leave
the buffer tail zero-filled and misclassify a loopback destination as
0.0.0.0. read_remote_mem rejects any short read, so the caller blocks
rather than allowing on a partial read.
Linux-only: seccomp and process_vm_readv(2) are Linux primitives.
Module: error
Section titled “Module: error”Module: identity
Section titled “Module: identity”Module: log
Section titled “Module: log”Swappable foreground log sink shared with the firma CLI.
firma run writes its own compact log lines to stderr by default. Once the
wrapped agent’s TUI takes over the terminal those lines would corrupt the
agent’s interface, so the sink is redirected to <dir>/run.log for the
duration of the session and restored to stderr for teardown output.
This module owns the pure, sink-swapping core — [ForegroundLog] and its
shared [ForegroundState] — with no dependency on tracing. The CLI wires
ForegroundState into a tracing layer: it resolves the active
destination on each write via [ForegroundState::write] and gates ANSI
color on [ForegroundState::is_stderr].
In file mode (--log-file) no compact stderr layer is installed, so the
handle is [ForegroundLog::idle]: redirect/restore are no-ops and the
destination is never consulted.