ADR-13: Process-adapter security boundary¶
Status: accepted (2026-05-29) Blocks: workstream A (runtime), workstream G (cross-cutting infra)
Context¶
Host controllers run arbitrary host code — Python and R subprocesses driven over the JSONL process-adapter protocol. A ControllerManifest that names an executable is, in effect, code the runtime will execute. Without a defined trust boundary, loading an untrusted manifest is a remote-code-execution vector, and a runaway adapter can hang or exhaust the host.
Decision¶
The runtime treats adapter execution as a privileged operation gated by an explicit, operator-controlled boundary:
Executable allowlist —
DAGML_ADAPTER_ALLOWLIST(colon-separated absolute paths). The runtime resolves an adapter’s executable and refuses to spawn anything not on the allowlist. Empty allowlist ⇒ no adapters spawn (default-deny).Environment sanitization — child processes receive a scrubbed environment. Only
PATH,PYTHONPATH, andR_LIBSentries that are themselves allowlisted pass through; everything else is dropped. The parent’s full env is never inherited.Per-task timeout + kill — every
NodeTaskcarries a wall-clock timeout. On expiry the runtimeSIGTERMs thenSIGKILLs the worker and emits acontroller_timeoutlineage event (ADR-12 span fieldcontroller_id).Tempdir isolation — each adapter task gets a per-task tempdir (
DAGML_PROCESS_ARTIFACT_DIR). Artifact URIs are validated against absolute/traversal paths (already enforced inbundle.rs); a traversal attempt is asecurityerror (ADR-11).Explicit warning — the CLI and docs state plainly that adapters execute untrusted host code, and that trusting a controller manifest equals trusting its code.
Optional sandbox hook — a pluggable wrapper (
cgroups v2/firejail/bubblewrap) gated behindDAGML_ADAPTER_SANDBOX. Off by default; documented for production operators who need resource and syscall confinement.
Consequences¶
The process-adapter spawn path in the runtime gains an allowlist check, an env scrubber, and a timeout/kill supervisor.
SECURITY.mddocuments this surface alongside ADR-16 (artifact deserialization is the other half of the host-trust boundary).The error taxonomy (ADR-11) gains
security/adapter_not_allowlisted,security/adapter_timeout, andsecurity/artifact_path_traversalcodes.
Risk¶
A locked-down default (empty allowlist) means a fresh install runs no adapters until configured. This is intentional: secure-by-default beats convenient-by-default for a code-execution surface. The CLI error names the env var and points at
SECURITY.md.