Agents run over SSH only; put the hardening back

The local sandbox is dropped before it was built. Every hard problem in it
came from running on the machine that holds the database and the encryption
key: the service user cannot traverse /home, granting it needs ACLs,
RLIMIT_NPROC is counted per uid so a fork bomb starves the server too,
--size only applies to tmpfs so there is no disk quota, and the bind list
is a standing invitation to widen until the sandbox is decoration.

Over SSH, isolation is somebody's considered choice of host -- a throwaway
container with one project mounted into it -- using tools far better at it
than anything that could be built here. It is also the only version that is
honestly multi-user: each person brings their own credentials and their own
machine, and picks a project directory on it.

So ProtectKernelTunables goes back. It was removed for exactly one reason,
that bubblewrap cannot mount /proc without it, and that reason is gone. The
agents settings group loses everything bwrap-shaped with it.

What this costs, and the admin copy has to say so: there was a network:False
switch that made exfiltration from a compromised reply impossible, and over
SSH there is no equivalent, because the network belongs to the far side.
The security of an agent chat is now the security of the host behind its
profile, and LLeMbas cannot tell a scratch container from a live server.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-08-01 22:12:48 +02:00
parent 671e49cae8
commit 0a4531f02d
3 changed files with 33 additions and 67 deletions
+10 -13
View File
@@ -81,21 +81,18 @@ delivers it in one lump at the end, which is indistinguishable from streaming
being broken. `proxy_read_timeout` is raised to an hour because a model can
think for minutes before the first token.
**Hardening is deliberately moderate.** `ProtectSystem=full`, not `strict`,
because agent chats run commands. Two lines in the unit are load-bearing and
worth knowing before anyone tidies them:
**Nothing an agent does runs on this machine.** Agent chats execute their
commands over SSH, on a host somebody added and prepared — a container, a VM,
another machine. That is the whole isolation story, and it is why the unit can
stay locked down instead of being opened up to make room for a sandbox.
- **`ProtectKernelTunables` is absent on purpose.** With it, bubblewrap cannot
start at all — it bind-mounts `/proc/sys` read-only, and the kernel then
refuses `mount -t proc` inside a user namespace. The unit says why, and why
the obvious workaround is worse.
- **`TasksMax` and `MemoryMax` bound the whole service**, because a sandbox has
no cgroup of its own and `RLIMIT_NPROC` is counted per uid — the same uid the
server runs as.
`ProtectSystem=full` rather than `strict` only because the data directory must
be writable and `strict` would mean listing every path.
Local agent execution is off until an administrator turns it on, and the
sandbox never binds the deployment prefix, so a command cannot read the
database or the encryption key.
The practical consequence for whoever runs this: **the security of an agent
chat is the security of the host behind its SSH profile.** A throwaway
container with the one project mounted into it is a very different thing from a
key to a production server, and LLeMbas cannot tell them apart.
**Use a real certificate if this is exposed beyond a trusted LAN.** The
self-signed cert exists so the install works with no external dependencies;