Skip to content

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 iss is 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 bindingaud must equal fold’s canonical resource URI (RFC 8707); there is no azp fallback.
  • RFC 9728 discovery — failures answer 401 with a WWW-Authenticate challenge pointing at /.well-known/oauth-protected-resource.

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 denialtools/call / prompts/get outside the allowlist answer 403, decided body-free from the Mcp-Method/Mcp-Name headers when present, and authoritatively re-checked after routing.
  • Invisibilitytools/list responses 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 defaultauthorization and cookie are stripped from every proxied request. What the upstream sees is the configured strategy’s decision:

StrategyIdentity at the upstream
token-exchange (RFC 8693)The end user, in a token minted for that upstream’s audience. Recommended.
client-credentialsfold’s service identity for that upstream.
staticA shared API key.
passthroughThe 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).

  • 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.