footprintai/containarium is an open-source agent runtime with native SSH isolation, eBPF egress policy, Kubernetes and LXC backends, GPU passthrough, and a native MCP CLI. The 2026-11-03 commit 4be7f81 (#3455, #3468) changed this runtime's internal/server logs to quote tenant-supplied strings with %q instead of %s.
The motivation was log forging and terminal control. A tenant-definable value such as a user name or a container name, if it carried a newline character, could forge a log line, and ESC characters could pass through to the operator's terminal unchanged. This change covers user names, box and container names, tracker connection and project names, volume and secret key names, process names, run ids and token ids, and it fixed 346 log.Printf calls in internal/server together with4 injected loggers in the run-checkout sweep. Operator- and daemon-side values such as configuration paths, IPs, durations, peer ids, enum states and server-generated ids were left as they were.
Verification came along with it. The 503-line log_quote_test.go injects a newline and \x1b into one handler per value family and checks that no control bytes and no forged lines are left in the log, and it walks the package AST so that the test fails if a log.Printf that binds a tenant-value expression to %s or %v comes back. A follow-up commit after review broadened this check to log.Print, Println, Fatal and Panic as well as the injected printf loggers, and quoted the jti and family id on the token rotation line and the checkout sweep name. Making the user-deletion failure log no longer append the name to the 'sudo userdel -r' hint is cleanup in the same family, because Go's %q is not shell quoting.
The limits clearly remain. As the changelog fragment spells out, error text appended after a log line is still not quoted with %v, so values embedded in errors can still break a line, and that is being tracked separately. If an existing log filter assumes the old format such as user=alice, it needs to be updated. Values now appear in the form user="alice", sweep lines in the form [run-checkout-sweep] "<name>-container":, and stderr captured from a box stays on a single line like stderr="line one\nline two". This is a defensive fix that blocks the path for polluting logs with tenant-supplied values and it comes with verification, but the residual error-path exposure and the filter migration are for the operator to handle.