SSRF
The service makes the call you didn't authorise.
An untrusted input becomes a URL. The service fetches it. Internal metadata, cloud creds, neighbour services, all readable from the inside.
Work / Enterprise & Security / Zero-Trust API Broker
Internal APIs are the new attack surface. SSRF, leaked tokens, over-broad service identities. The broker stops all three. Every request is authenticated. Every token is scoped. Every hop is mutual TLS. Every call leaves a signed audit log on its way out, even if your team forgets to log it.
Act I · The Problem
External breaches make headlines. Internal misuse drains balance sheets. The broker stops the three failure modes that show up in every post-mortem.
SSRF
An untrusted input becomes a URL. The service fetches it. Internal metadata, cloud creds, neighbour services, all readable from the inside.
Leaked token
A debug print, a CI log, a misconfigured Sentry, and the long-lived service token is in the wild. The token has admin scope on six services it never needed.
Over-broad identity
So it got blanket access. Now any code path under that service identity can read every row, drop every table, call every other API in the mesh.
Act II · The Promise
A request that survives all five gates is allowed and audited. A request that fails any gate is rejected and audited. There is no other path.
The caller presents a client certificate. The broker pins it to a known service identity. No certificate, no conversation. No fallback to bearer-only.
AuthenticatedEach token carries the minimum scope for one action against one upstream. Scope mismatch is a hard reject. Tokens are short-lived and rotate on each call.
AuthorisedThe upstream URL must resolve to an entry in the registry. Arbitrary URLs are rejected. SSRF is a category error here, not a vulnerability.
RoutableRequest body validated against a registered schema. Headers stripped to the required set. Size capped. Anything weird, dropped before it reaches the upstream.
ValidatedBroker signs the audit entry, then issues the upstream call over its own mTLS connection. Upstream sees a stable broker identity, not the original caller.
Forwarded · signedAct III · The Receipt
No buffering. No batching. No "the agent crashed before the log shipped". The audit entry is written, signed, and emitted before the upstream sees the request.
{
"v": "ztb-1",
"ts": "2026-05-04T11:42:08.317Z",
"call_id": "01HX9GZ6P7B2WMK0RTV3F8N4QE",
"caller": {
"spki": "sha256:b1f4...e22a",
"identity": "svc.checkout"
},
"upstream": {
"name": "orders.api.internal",
"path": "/v1/orders/create",
"method": "POST"
},
"token": {
"scope": ["orders:create"],
"exp_in_s": 60
},
"shape": {
"schema": "order.create.v3",
"bytes": 412,
"sha256": "4a8d...c19f"
},
"decision": "ALLOW",
"latency_ms": 3,
"prev_hash": "7e0c...9d31",
"sig": "ed25519:9f...7c" // signed before egress
}
prev_hash → curr_hash. Tampering one entry breaks the chain for every entry after it.Act IV · The Pattern
The broker is the API-shaped sibling of Zero-Trust MySQL. Both refuse to trust the network, the operator, and the caller. Both produce a hash-chained audit pack the auditor accepts. Both prefer a small, verifiable surface to a large, "configurable" one.
Nothing routes, nothing decrypts, nothing executes unless an explicit policy says so. New endpoints are off until they are registered.
Fail closedHash-chained entries. Off-host anchor. Signed before emission. Auditor walks the chain and verifies continuity end to end.
Tamper-evidentControls expressed as scripts that pass or fail. Evidence bundle generated on demand. No self-signed compliance reports.
VerifiableCompromise a caller, you get one short-lived token with one scope on one endpoint. The blast radius is one row, not one cluster.
ContainedAct V · Proof
Ed25519 signature emitted before the upstream sees the request. Hash chained. Off-host anchor. Tampering one entry breaks every entry after.
One scope, one upstream, one minute. Rotated per call. Leaking a token leaks one minute of one action against one endpoint.
Caller to broker, broker to upstream. SPKI-pinned. No bearer-only fallback path. No anonymous calls anywhere on the data plane.
Upstream URLs come from the registry, not the request. SSRF is a category error here, not a CVE. Untrusted URLs cannot be resolved.
Body validated against a registered schema. Headers reduced to the required set. Size capped. Anything weird is dropped at the gate.
The default path is the only path. There is no "skip the gate for performance" flag. Misuse requires a code change and a registry change, both reviewed.
I build internal API gateways that prefer one verifiable path to ten configurable ones. Default deny. Signed audit. Scoped tokens. The gate makes the right thing the easy thing.