DEV Community

wartzar-bee
wartzar-bee

Posted on Originally published at github.com

Your agent's 'secure' network policy was off unless you did four steps — so it was off

If you run an autonomous LLM agent in a container, here is a question worth sitting with: is your
network egress policy actually enforced, or is it enforced if you performed a setup ritual you did
once, months ago, on one machine?

We shipped enclave 0.8.0 (Apache-2.0, the sandboxed runtime
our own agent fleet runs on) around exactly that failure mode. The short version: a safety control
with a four-step activation cost is, in practice, off
— and "off unless you opt in" reads on a
dashboard identically to "on." That gap is the vulnerability.

The concrete bug: "scoped credentials" that weren't

Mounting your secrets/ directory read-only (:ro) feels like scoping. It isn't. :ro stops
writes; it does nothing about reads. A compromised or prompt-injected agent reads every file it
can see — so "scoped credentials" was only ever true if the directory was scoped, not the mount
mode. 0.8.0 makes SECRETS_DIR scope the mount and adds SECRETS_SCOPE so a pod declares what it
actually needs, instead of getting handed the whole vault behind a :ro flag that reads as safe.

Same theme across the release:

  • Kernel egress default-deny is now scaffolded by enclave new (--unsafe-network opts out). It was never "off by default" — it was off unless you ran a four-step manual ritual, and that activation cost was the hole. The real network wall is a sidecar owning the agent's netns with a DNS proxy + nftables default-deny that command-string tricks (U=$host; curl $U) can't walk around.
  • web_chat refuses to start on a non-loopback bind with an empty token — including when the bind var is unset, because absent evidence of loopback is not evidence of loopback. The server binds 0.0.0.0 inside the container by necessity, so the only thing between a changed bind and an unauthenticated control surface into a PERMISSION=dangerous agent was the Docker publish — and nothing cross-checked the two.
  • An allowlist for a scanner that didn't exist. .publish-audit-allow had shipped with no enforcer — grep found exactly one reference to the file: itself. An allowlist for a control that doesn't run reads as a working control, which is worse than none. 0.8.0 ships the scanner, in CI, failing closed if the allow file goes missing.

The pattern: a probe that returns exists(), not works()

The one I like most is smaller. Our image-capability preflight returned path.exists() on the API
key file. So through a whole stretch where a pod's key answered 401 on every call, the capability
board cheerfully read image: ok — key present. The false alarm and the false all-clear were equally
invisible; a resolved blocker stayed quoted as open for days. It now authenticates against the
provider's free key-check endpoint (no generation spend): 200 → works, 401 → present but dead (with
the refresh instruction), anything else → inconclusive. "Present" is not "works," and a probe that
can't tell dead from down diagnoses neither.

If you maintain agent infra, audit your health checks for this class: every exists() that stands
in for works() is a green light wired to nothing.

Why a cost-efficiency project cares about this

enclave exists to run autonomous agents cheaply — model-tier routing, manager→worker delegation,
and measuring token spend instead of guessing at it. Safety and cost are the same discipline: both die
the same way, to a default that looks fine on a dashboard and isn't. The same cost discipline ships as
two standalone tools you can drop into any project, no runtime required:

  • tokenscopenpm i -g @wartzar-bee/tokenscope — measures the token cost of prompts, files, and diffs so you see what a change costs before you pay.
  • ci-guardrail — a GitHub Action that predicts a PR's token-cost delta, comments on the responsible files, and fails the build on a regression.

Full changelog: enclave 0.8.0.
It's a public alpha we run daily against a live fleet — issues and bridges welcome.

Top comments (0)