Security model
Tools are the part of an agent most likely to be untrusted — third-party code, generated code, code you’d rather not fully audit. maiden runs every tool inside a WebAssembly sandbox with no ambient authority, and mediates the few things a tool can do at the host boundary.
The trust boundary
Section titled “The trust boundary”A tool is a WASI-P2 component. It exports three functions maiden calls
(describe, schema, execute) and it may import only what maiden’s contract
grants it. It cannot open files, spawn processes, or reach the network on its
own — a fresh WASM instance has no capabilities until the host links them in,
and maiden links in only a narrow, gated host interface.
The host enforces three things on every execute call:
1. A wall-clock deadline
Section titled “1. A wall-clock deadline”Each tool runs under an epoch-based deadline derived from its timeout_ms
policy. A background ticker advances the engine’s epoch; a tool that runs past
its deadline traps and the call returns an error. A runaway or infinite-loop
tool cannot hang the agent.
2. A memory ceiling
Section titled “2. A memory ceiling”The tool’s WASM store is capped at its memory_mb policy via store limits. A
tool that tries to allocate past the ceiling is denied the growth rather
than being allowed to exhaust host memory.
3. A capability-gated egress boundary
Section titled “3. A capability-gated egress boundary”This is the important one. A tool never holds a secret and never has an open
door to the network. When a tool wants to make an HTTP request, it calls the
host’s http-fetch with:
- the URL, plus an optional method, headers and body, and
- a credential name (never a value).
The host then, in order:
- Extracts the URL’s host and checks it against the tool’s
http_allowallowlist (exact match, or a single-label*.example.comwildcard). A host that isn’t on the list is refused before any network call happens. - Requires
https(plainhttponly for loopback) — a request the host is about to authenticate must not go out in the clear. - Checks the credential name against the tool’s
secretslist. A tool may only spend a credential its own policy declared; naming some otherMAIDEN_SECRET_*that happens to be in the process environment is refused. - Resolves that name from
MAIDEN_SECRET_<NAME>and attaches it as anAuthorization: Bearerheader. - Sends the request with redirects disabled. A redirect is a second
request, and following one would let an allowlisted host hand the tool a
Locationpointing anywhere. The 3xx returns to the tool as an ordinary response instead.
The request is bounded by the tool’s timeout_ms — the same budget the rest of
its execution spends from — and the response body is capped at 2 MB.
The secret value never crosses into the WASM instance. The tool’s code only ever
sees a name like TFL_TOKEN; the mapping from name to value lives entirely in
the host. A compromised or malicious tool cannot exfiltrate a credential it was
never given, and cannot reach a host it wasn’t allowlisted for.
Why name-only credentials matter
Section titled “Why name-only credentials matter”Passing a secret value into tool code means the secret is only as safe as the
least-trusted line in that tool. Passing a name inverts it: the tool declares
which credential it needs (and agent.toml must grant it via secrets), but
the host holds the value and decides when to attach it. The blast radius of a
bad tool shrinks from “can leak my API keys” to “can make allowlisted requests
that the host chose to authenticate.”
What the boundary does not cover
Section titled “What the boundary does not cover”The allowlist is by host name, not by address. If a name on a tool’s allowlist resolves to an address inside your network, the tool reaches it — allowlisting a host is an explicit grant, so grant hosts you mean. maiden does not resolve-and-check addresses, and does not re-resolve between the check and the request.
The allowlist also says nothing about what a tool sends to a host it is
allowed to reach. A tool that legitimately talks to api.example.com can send
whatever it likes there, including data it was given as input. The boundary
bounds reach and credential custody, not intent.
Component caching and hot reload
Section titled “Component caching and hot reload”Compiled components are cached by path and modification time, so repeated tool
calls don’t recompile. Editing a tool’s .wasm on disk invalidates its cache
entry, so the next call picks up the new version — useful during development,
and never a way to bypass the policy, which is applied fresh on every call.