Security & governance
fold is the single governed boundary between every MCP client in the company and every team’s MCP server. Four subsystems compose the governance story.
Authentication — fold as OAuth 2.0 resource server
Section titled “Authentication — fold as OAuth 2.0 resource server”With auth.mode: "required", every /mcp request presents a Bearer token:
- Issuer allowlist first — the token’s
issis checked against configured issuers before any network I/O (RFC 9207 posture). - JWKS verification — signatures verified against the issuer’s key set, KV-cached with a kid-miss refresh and anti-stampede cooldown. Algorithms are allowlisted (RS256/ES256/EdDSA).
- Hard audience binding —
audmust equal fold’s canonical resource URI (RFC 8707); there is noazpfallback. - RFC 9728 discovery — failures answer 401 with a
WWW-Authenticatechallenge pointing at/.well-known/oauth-protected-resource.
Enterprise-Managed Authorization (EMA)
Section titled “Enterprise-Managed Authorization (EMA)”fold ships an embedded authorization server exactly one grant wide: the
ID-JAG exchange from the MCP Enterprise-Managed Authorization extension. The
enterprise IdP (Okta, Entra, Auth0) evaluates its policy when it issues the
ID-JAG — gate one. fold validates it and mints a short-lived ES256 token with
aud = fold — so everything the gateway later accepts has a coherent audience,
which is what makes upstream token exchange sound. fold’s policy engine is
gate two.
Authorization — the allowlist policy engine
Section titled “Authorization — the allowlist policy engine”First-match rules over (principal, client, server, method, name-glob) with
defaultDecision: "deny" as the enterprise default. Enforcement is a pair:
- Call denial —
tools/call/prompts/getoutside the allowlist answer 403, decided body-free from theMcp-Method/Mcp-Nameheaders when present, and authoritatively re-checked after routing. - Invisibility —
tools/listresponses are filtered per principal on egress. Callers never see tools they cannot call.
The engine sits behind a three-method interface so Cedar or OPA can replace it without touching callers.
Upstream credentials — the token boundary
Section titled “Upstream credentials — the token boundary”Client credentials never cross the gateway by default — authorization
and cookie are stripped from every proxied request. What the upstream sees
is the configured strategy’s decision:
| Strategy | Identity at the upstream |
|---|---|
token-exchange (RFC 8693) | The end user, in a token minted for that upstream’s audience. Recommended. |
client-credentials | fold’s service identity for that upstream. |
static | A shared API key. |
passthrough | The raw client token — its audience is fold, so strict upstreams will reject it. Use knowingly. |
Minted tokens are cached until shortly before expiry with in-flight coalescing, so bursts never stampede a token endpoint.
Audit — every terminal response, one exit door
Section titled “Audit — every terminal response, one exit door”The pipeline observes every response — including 401s, 403s, and 429s, which
are the events security teams actually hunt — through a single exit path, so
nothing can bypass audit. Each event carries the principal (sub, issuer,
client, groups), the request (method, tool, upstream, protocol era), the
authz decision with the matching rule id, the outcome, and latency. Sinks:
stdout JSONL and webhooks today; the schema is versioned (v: 1).
Transport hardening
Section titled “Transport hardening”- DNS-rebinding protection: Host/Origin validated against
allowedHosts(localhost by default — set your public hostnames in production). - Fold-owned legacy session ids never reach upstreams; upstream sessions never reach clients.
/health/upstreams(circuit-breaker topology) is Bearer-guarded whenever auth is required.