From 2d6ac0b7e7438edcb97cbf82965cbabcc926d57c Mon Sep 17 00:00:00 2001 From: damocles Date: Thu, 12 Nov 2026 10:49:50 +0100 Subject: [PATCH] swarm-stt: say plainly that the network is not restricted and the decoder can read the unit's credentials --- docs/2-handbook/swarm/services.md | 7 +++++-- nix/host-modules/swarm-stt.nix | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/2-handbook/swarm/services.md b/docs/2-handbook/swarm/services.md index 70447ce46..84f229275 100644 --- a/docs/2-handbook/swarm/services.md +++ b/docs/2-handbook/swarm/services.md @@ -435,8 +435,11 @@ how many requests it holds at once are settings next to it. The audio comes from rooms with outside people, so the service runs as its own unprivileged user under a tight systemd sandbox, with a memory ceiling and -a CPU quota, and the container reaches the queue, the store and authelia -and nothing else. The file's first bytes must look like an audio container +a CPU quota. Its network isn't restricted: the decoder runs in the same +network namespace as the service and can read its credentials, so a decoder +exploit could read them and send them anywhere the container can reach. Closing +that's for the strict-egress work on service containers, or for running the +decode with no network and no credentials. The file's first bytes must look like an audio container before anything decodes it. Its leaf and its queue client work as the router's do. The design, the settings and the reasons are in [`stt.md`](../../4-implementation/swarm/stt.md). diff --git a/nix/host-modules/swarm-stt.nix b/nix/host-modules/swarm-stt.nix index ec89de144..b88811d79 100644 --- a/nix/host-modules/swarm-stt.nix +++ b/nix/host-modules/swarm-stt.nix @@ -12,7 +12,16 @@ # # Its own network namespace on the bridge, as ./swarm-claude-login.nix has: it # reaches the swarm services by name and nothing on the host's loopback. It -# talks only to the queue, the store and authelia, so it can run on any host. +# needs only the queue, the store and authelia, so it can run on any host. +# +# ⚠️ Nothing here limits what it may reach: the container's egress is whatever +# the bridge and the host's NAT allow. `ffmpeg` and `whisper-cli` run as +# children of the daemon, in the same network namespace and user, and can read +# the unit's credentials (the store leaf, the queue client secret). A decoder +# exploit on a hostile file could read them and send them out. The sandbox +# below narrows what such an exploit can do on the host; the network side +# waits on the strict-egress series covering service containers, or on running +# the decode in a child with no network and no credentials. # # The container holds one credential, its own store leaf, which nspawn hands in # as a system credential with no copy on disk. The daemon reads its queue @@ -315,9 +324,8 @@ in # The sandbox for a service that decodes files strangers sent: # the only writable path is its state directory, it sees no - # other user's processes or devices, cannot gain privileges, and - # may open sockets to the queue, the store and authelia only - # (the container's netns has no other route). + # other user's processes or devices, and cannot gain + # privileges. It does NOT limit the network (see the header). StateDirectory = unit; StateDirectoryMode = "0700"; NoNewPrivileges = true;