Security boundaries and trust zones#
MAQPNA treats agent code as untrusted and puts a boundary, with its own credential, between every pair of zones. This page maps the zones and the crossings. The threat model behind it is in security model and what "sovereign" means.
Zones#
flowchart LR
subgraph Z1["Zone 1: untrusted, agent sandbox (per session)"]
AG["agent process<br/>read-only token file"]
SC["sidecars: egress-relay, browser, exec,<br/>attest init and renewer"]
end
subgraph Z2["Zone 2: data plane, maqpna-system"]
GW["gateway"]
end
subgraph Z3["Zone 3: control plane, maqpna-system"]
OP["operator"]
IB["identity broker"]
AT["attestation service"]
PG[("PostgreSQL")]
end
subgraph Z4["Zone 4: customer services"]
IDP["identity provider (OIDC)"]
TR["Trustee verifier"]
KMS["key store: file, Azure Key Vault"]
WORM[("WORM and SIEM")]
end
subgraph Z5["Zone 5: upstreams (untrusted)"]
MCP["MCP servers"]
LLM["model endpoints"]
PEER["remote A2A peers, web"]
end
subgraph Z6["Zone 6: Kubernetes API and nodes"]
K8S["API server, etcd, kubelet"]
end
AG -- "1 session token" --> GW
SC -- "2 session token (Proxy-Authorization)" --> GW
GW -- "3 upstream credential or Txn-Token" --> MCP & LLM & PEER
OP -- "4 MAQPNA_BROKER_TOKEN" --> IB & AT
SC -- "5 projected SA token" --> IB
SC -- "6 hardware evidence" --> AT
AT -- "7 evidence" --> TR
GW -- "8 DSN credential" --> PG
GW -- "9 residency-checked TLS" --> WORM
IDP -- "10 OIDC tokens for admins" --> GW
OP & GW -- "11 ServiceAccount" --> K8S
| Zone | Trust | Notes |
|---|---|---|
| 1. Agent sandbox | Untrusted | Runs model-generated code. gVisor, microVM or confidential VM; non-root, read-only root filesystem, no ServiceAccount token, default-deny NetworkPolicy |
| 2. Gateway | Trusted to enforce | The only exit from zone 1. Holds upstream credentials, the audit ledger and the approval queue |
| 3. Control plane | Trusted | Operator, identity broker, attestation service, PostgreSQL. Not reachable from agent namespaces except the broker's bootstrap port and the attestation port when needed |
| 4. Customer services | Trusted (the root of trust) | Your identity provider, verifier, key store and evidence storage |
| 5. Upstreams | Untrusted | Their output can taint sessions; their credentials never reach zone 1 |
| 6. Kubernetes and nodes | Trusted for scheduling and integrity | For tier-2 sessions, not trusted with confidentiality: the confidential VM boundary excludes the host |
Crossings#
| # | Crossing | Credential | Checked by |
|---|---|---|---|
| 1 | Agent → gateway (MCP, model, A2A) | Session token: Ed25519 JWT, aud maqpna-gateway, scoped, about 15 minutes; optionally bound to an X.509-SVID |
Gateway: signature, expiry, audience, scope, kill switch, tenant key |
| 2 | Browser sidecar → gateway egress proxy | Session token in Proxy-Authorization: Bearer, added by the egress relay; the browser never sees it |
Gateway egress proxy: scope tools:maqpna-egress, domain policy |
| 3 | Gateway → upstream | The gateway's own credential per MCPServer.spec.auth (bearer, header, OAuth client credentials, token exchange, mTLS, or the user's own token from the vault), plus X-Maqpna-* identity headers or a Txn-Token. The agent's token is always stripped |
The upstream |
| 4 | Operator → identity broker and attestation service | MAQPNA_BROKER_TOKEN (static bearer, from a Secret) |
Broker and attestation service |
| 5 | Warm-pool pod → identity broker bootstrap port | Projected ServiceAccount token, audience maqpna-bootstrap, at most one hour |
Broker: TokenReview, pod → Sandbox → SandboxClaim → AgentSession ownership chain |
| 6 | Attest agent → attestation service | Hardware report binding a nonce and an ephemeral key; optionally TLS and signed responses | Attestation service: verifier, reference values, single-use release |
| 7 | Attestation service → verifier | Evidence; the verifier answers with a signed JWT | Attestation service: JWKS, exp, iss, maximum age |
| 8 | Gateway, attestation service → PostgreSQL | DSN from a mounted file (never inline) | PostgreSQL |
| 9 | Gateway → WORM and SIEM | S3 SigV4 keys or sink headers from Secrets; TLS | The residency dialer before connecting |
| 10 | People → gateway admin API | OIDC access token (roles from groups) or the static admin token (break-glass) | Gateway: issuer, audience, role per endpoint |
| 11 | Operator, gateway → Kubernetes API | ServiceAccount with least-privilege RBAC; the gateway may only patch session annotations, MCPServer pin reports, create break-glass revocation mirrors and connected accounts | API server |
What never crosses#
- Raw arguments into the ledger. The ledger stores
argsSha256; argument capture for replay is opt-in, DLP-redacted and sealed with AES-256-GCM. - Upstream credentials into the sandbox. Tool and model keys live in gateway-only Secrets (
maqpna-upstream-credentials,maqpna-model-credentials); the sandbox only knows{gateway}/mcp/<name>and{gateway}/llm/<route>/v1. - Tokens into etcd for tier-2 and warm-pool sessions. Attested sessions get the token sealed to a key inside the confidential VM, written to a memory-backed volume; warm-pool sessions get it from
/v1/bootstrapat runtime. Only direct-mode, non-attested sessions use a token Secret (<session>-maqpna-token). - Users' OAuth tokens to agents. The token vault injects them at the gateway;
ConnectedAccountobjects hold status only. - Vendor traffic. No telemetry, update check or licence call leaves the installation.
- The broker token to agent namespaces. Agent namespaces reach the broker only on the bootstrap port, never the mint port.
What you see#
The identity a sandbox holds can be decoded without trusting it. maqpna token inspect prints a warning on stderr and the claims as JSON (format from cmd/maqpna/token.go; values illustrative):
$ maqpna token inspect "$(cat /var/run/maqpna/token)"
! Signature not verified: inspect only decodes the token.
→ maqpna token verify TOKEN --jwks URL
{
"claims": {
"iss": "maqpna-identity",
"sub": "spiffe://maqpna.local/ns/team-a/agent/coder/session/fix-4821",
"aud": "maqpna-gateway",
"iat": 1790933991,
"nbf": 1790933991,
"exp": 1790934891,
"jti": "5f0c2a9e41b7d3a86e2f1c0b9d4a7e31",
"act": {
"sub": "user:alice@acme.eu"
},
"scope": "tools:github models:team-a.coder",
"maqpna_tier": "tier-1-microvm",
"maqpna_session": "fix-4821",
"maqpna_ns": "team-a",
"maqpna_agent": "coder",
"maqpna_principal_verified": "requester"
},
"expiresAt": "2026-10-02T14:21:31Z",
"kid": "Xh3m…"
}
maqpna token verify checks the signature against the broker's public keys. See maqpna token inspect and maqpna token verify.