Skip to content
agentics.download

The guarding

Assume the tool misbehaves.

Agent tooling fails differently from ordinary software: the caller is a language model that can be manipulated, and the payload is your accounts. Every layer here exists to make the worst case boring. It's best-effort, shown in full — open to read line by line, so none of it asks for your trust.

The request path

What stands between Claude and the internet.

Claude desktop / web / mobile   custom connector, private to your account
   │ HTTPS
   ▼
Cloudflare edge                 TLS · hides home IP · WAF
   │ outbound-only tunnel       zero inbound ports on the boxtool container                  FastMCP · OAuth + email allowlist, fail-closed
   │ sealed internal network    output screened by the guardrail sidecaregress proxy                    per-tool allowlist · default-deny · audit log
   ▼
only the APIs this tool needs   everything else: TCP_DENIED/403, logged

The same image runs this path locally and in the cloud — transport and security posture are read from env at startup, so one image serves every environment.

Guard by guard

Seven controls, each with a reason.

01 egress

Default-deny egress

the strongest single control

Each tool sits on an internal Docker network whose only route off-box is a squid sidecar enforcing a per-tool domain allowlist. A tool reaches the handful of hosts it needs; everything else returns TCP_DENIED/403, logged to a central audit. Verified behavior — allowlisted hosts succeed, the rest are denied, and a proxy-bypass attempt is dropped.

02 isolation

One tool per container

a bug stays one box

Every tool is its own image with its own secrets and its own subdomain, on a sealed network. When two must cooperate they exchange artifacts through a shared volume — exactly one writer, the format is the contract — so no tool ever holds another's credentials or network access.

03 oauth

Auth in the server, fail-closed

travels with the image

Each MCP server runs its own Google OAuth with a verified-email allowlist, and starts only once an allowlist and credentials are present. Because auth lives in the image, the same container authenticates the same way on a laptop or a cloud VM, across Claude desktop, web, and mobile.

04 no-ports

Zero inbound ports

the tunnel dials out

A Cloudflare Tunnel sidecar dials outbound to serve each tool's subdomain — TLS at the edge, home IP hidden, the box listening on nothing. The tunnel is transport only; auth stays in the server, so there's a single identity layer.

05 guardrail

A guardrail that proves itself

fails closed

A sidecar screens tool output for prompt injection before it reaches the agent. GUARDRAIL_PROVIDER picks the engine — llamafirewall locally, Bedrock Guardrails on AWS — behind a fixed contract. At startup a canonical injection must block, or the container refuses to report healthy.

06 approval

Human approval, out of band

written by humans only

Gated actions post an Approve/Deny card to a channel you own — Slack, Discord, or Telegram. Decisions are written solely by those human channels (signed webhooks or a capability-URL page); a tool can create and query its own approvals, and the decision stays with the human on a platform the agent doesn't operate.

07 supply-chain

Supply chain, locked

CI holds the line

Every tool's dependencies are hash-locked, and CI installs in require-hashes mode, so an unlocked or tampered dependency stays out of main. Dependabot watches each tool's directory, and test_stack.py fails any PR that skips a wiring step, naming the missing piece.

Read it, don't trust it

Verify every claim on this page.

A security page is worth exactly what you can check. Every guard above maps to code and configuration in the public repo — the egress config, the auth wrapper, the guardrail contract, the CI checks. Read ARCHITECTURE.md, then read the code it points to.

The whole design is in the open.

Read the architecture, follow it into the code, and file what you find.

Read ARCHITECTURE.md