
Auditing an LLM Gateway for Auth Bypass, API-Key Exposure, and Tenant Leaks
Introduction
Two stories dropped within 48 hours of each other, and they belong together. Reporting attributed to a Semperis report — covered by Quartz on 2026-10-15 — says attackers used AI in most ransomware campaigns and leaned on a nastier tactic: threatening staff directly. A day earlier, SC Media described AI agents breaching production systems to spread malware. Then on 2026-10-15, Infosecurity Magazine flagged high-risk vulnerabilities in a widely used LLM gateway.
Everyone watches the model. The LLM gateway is the better target. It holds provider API keys, the tenant routing table, and every tenant's prompts and completions in one process, and it usually sits on the same internal network as everything else.
This post is not a teardown of the unnamed gateway in that Infosecurity warning. The public material does not name the vendor, the affected versions, the CVE IDs, or the exploit prerequisites, and I am not going to invent them. What I can offer is the LLM gateway audit I would run against my own deployment — control-plane auth bypass, provider API-key exposure, and cross-tenant leaks through shared cache and logs — in the order I would run it, with the probes and the evidence I expect to see at each step.
What the public reporting confirms and what it leaves unknown
Before any technical claim, the split.
Confirmed by the source material: a Semperis-attributed report covered by Quartz on 2026-10-15 found attackers used AI in most ransomware attacks and threatened staff; a GBHackers headline the same day puts the figure at 84% and describes identity infrastructure under pressure; SC Media reported on 2026-10-14 that AI agents breached production systems to spread malware; Infosecurity Magazine reported on 2026-10-15 that high-risk vulnerabilities were found in a widely used LLM gateway tool.
Explicitly unknown: the gateway vendor, the affected version range, any CVE identifiers, whether the flaws were remotely reachable or needed an authenticated account, and whether they were exploited in the wild. I have no information on any of that, so nothing below depends on it.
Everything that follows is a generic audit you can run against a gateway you own. It is not a reproduction of an unnamed advisory, and it makes no claim about routes or versions in that product.
Why an LLM gateway is a key vault, not just a proxy
The gateway terminates tenant authentication, holds upstream provider keys in plaintext or reversible form, maps tenant IDs to upstream accounts and budgets, caches prompts and completions, writes logs, and decides which tools an agent may call. Six privileged systems in one service.
| Asset | Why it is valuable | Typical weak control |
|---|---|---|
| Provider API keys | Billing and abuse under your identity | Stored in the config DB, readable from any admin route |
| Tenant routing map | Tenant IDs, upstream accounts, budgets | Control-plane route with no per-route authorization |
| Prompt/completion log | Customer data, sometimes regulated | One shared table, filtered by tenant in the UI only |
| Semantic cache | Another tenant's answers | Cache keyed on prompt hash, no tenant in the key |
| Usage/billing export | Row-level activity per customer | Endpoint checks the caller's role, not the tenant |
| Tool-call policy | Which functions an agent may invoke | Policy shipped with the agent, not enforced at the gateway |
My honest read: most teams spend their entire security review budget on the model provider and none on the thing sitting in front of it. The gateway is where the blast radius lives, and it is where multi-tenancy actually gets decided.
Audit 1 — testing the control plane for auth bypass
Do not start at the chat endpoint. Start with the routes nobody demos: /v1/admin/config, /v1/admin/models, /v1/admin/keys/rotate, /v1/admin/usage/export, /v1/playground, and anything that returns provider credentials. These get added late, tested by hand, and left out of the middleware chain because someone decided they were "internal".
The probes that find a control-plane auth bypass
Run these against infrastructure you own, in this order:
- Replay a valid JWT from a low-privilege tenant account against every admin route and record the status codes.
- Strip the
Authorizationheader entirely and watch for200where you expected401. - Swap
GETforPOST,PUT, andDELETEon the same path — method-based middleware often covers only one verb. - Try path normalisation:
/v1//admin,/v1/admin/../admin,/v1/admin%2f..%2fadmin. A router and an auth middleware can disagree about what the path is. - Test trusted-header spoofing (
X-Forwarded-User,X-Internal-Role, or a role derived fromX-Forwarded-For) when the gateway sits behind a proxy that does not strip inbound copies.
# 1. Valid low-privilege JWT against an admin route
curl -s -o /tmp/a.json -w "%{http_code}
" -H "Authorization: Bearer $LOW_PRIV_JWT" https://gw.internal.example/v1/admin/tenants
## 2. No Authorization header at all
curl -s -o /tmp/b.json -w "%{http_code}
" https://gw.internal.example/v1/admin/configThe evidence you want is the status code sitting next to the body:
200 # expected 403 — body contains the tenant list
200 # expected 401 — body contains model registry + upstream base URLs
To be clear: this transcript shows the shape of the finding, not a capture from the unnamed gateway in the Infosecurity warning. I have not tested that product and cannot claim these routes exist in it.
Only run these probes against systems you own or are contracted in writing to test. Auth-bypass probing against a third-party gateway is unauthorized access even when the flaw is real.
Why an auth bypass here is the pivot finding
An auth bypass on the control plane takes every other latent flaw from theoretical to live. The attacker can mint keys, rotate provider credentials, read the tenant routing map, and pull usage exports — all carrying the gateway's own authority. Nothing else on this list shifts attacker capability that far.
Audit 2 — hunting provider API-key exposure
Keys escape through boring paths. Error bodies that echo the upstream request, including the Authorization header. Debug or /metrics endpoints that serialise config. Streamed SSE frames that pass raw provider responses through. Unhandled exceptions with a stack trace and the offending config object. Tenant-visible usage or log exports that include the request envelope.
Run one shared upstream key for all tenants and that is not one leak — it is a single billing and abuse incident touching every tenant at once, plus a rotation that breaks everyone simultaneously.
The API-key scrubbing test
Turn "we redact secrets" into an observed result. This scanner walks any JSON response or log line and reports the exact field path.
const KEY_PATTERNS = [
{ name: "openai", re: /sk-(?:proj-)?[A-Za-z0-9_-]{20,}/ },
{ name: "anthropic", re: /sk-ant-[A-Za-z0-9_-]{20,}/ },
{ name: "google", re: /AIza[0-9A-Za-z_-]{35}/ },
{ name: "aws", re: /AKIA[0-9A-Z]{16}/ },
// tripwire only: matches hashes and base64 IDs too
{ name: "entropy", re: /[A-Za-z0-9+/]{40,}={0,2}/ },
];
function scan(value, path = "$", hits = []) {
if (typeof value === "string") {
for (const { name, re } of KEY_PATTERNS) {
const m = value.match(re);
if (m) hits.push({ path, rule: name, prefix: m[0].slice(0, 6) + "…" });
}
return hits;
}
if (value && typeof value === "object") {
for (const [k, v] of Object.entries(value)) scan(v, path + "." + k, hits);
}
return hits;
}
const raw = require("fs").readFileSync(0, "utf8");
const hits = scan(JSON.parse(raw));
console.log("matches: " + hits.length);
for (const h of hits) console.log(h.path + " rule=" + h.rule + " prefix=" + h.prefix);$ node key-scan.js < /tmp/resp.json
matches: 0
$ node key-scan.js < /tmp/err.json
matches: 1
$.error.upstream_request.headers.Authorization rule=openai prefix=sk-pro…
The entropy rule will fire on request IDs and content hashes. Treat it as a pointer, not proof — check the format against the provider's documented prefix before calling it a leak. On a confirmed hit, rotate first and investigate second; then find the single write path that serialises the config object and fix that, rather than bolting a regex filter onto the edge.
Audit 3 — testing shared state for cross-tenant leaks
Tenant isolation usually fails in caching and logging, not in the auth layer. The auth layer is just where people look.
Testing semantic and prompt caches for tenant bleed
Take two accounts. Send the identical prompt from tenant A, then from tenant B, and inspect B's response. You want to know two things: did B receive A's cached completion, and does any cache-hit header reference A's tenant ID.
POST /v1/chat/completions
Authorization: Bearer $TENANT_B_JWT
{"model":"gpt-4o-mini","messages":[{"role":"user","content":"summarise our Q3 refund policy"}]}
HTTP/1.1 200 OK
x-gw-cache: hit
x-gw-cache-tenant: tenant_A_acme
That header is the whole bug. The request pair plus the observed response field is the evidence; a screenshot would be weaker. Embedding-similarity caches widen this from exact matches to near matches, which turns a caching quirk into a data-exposure bug.
Reading logs, usage exports, and vector namespaces
Check the read paths. A shared log view that filters by tenant in the UI only. Usage exports with prompts in them. Vector or index names namespaced by naming convention (acme_chunks) instead of by enforced access control.
The check is one request: authenticate as tenant B, ask for tenant A's object identifier directly — a known log ID, export job ID, or vector namespace — and record the status code and whether content or metadata came back. 403 is the answer you want. 200 with metadata is a finding; 200 with content is a report.
Which LLM gateway finding I would fix first
| Rank | Finding | Why it ranks here |
|---|---|---|
| 1 | Control-plane auth bypass | Confirmed exploitation path, and it grants further access |
| 2 | Provider key exposure | Secret disclosure with direct cost impact and a clear write path |
| 3 | Cross-tenant cache or log leak | Real data exposure, but read-only and usually narrower in blast radius |
Confirmed exploitation paths beat theoretical ones, and anything that grants more access beats anything that only reads. A vendor advisory listing several high-risk issues with no prioritisation is not useful to a defender — ranking is the reviewer's job, not the vendor's.
Hardening the gateway itself
- Default-deny authorization on every route. Deny unless a route explicitly opts in, not the reverse. A route added on a Friday should be closed by default.
- Keys never in a response, log, or metric path. Store them in a secret manager with per-tenant scoping, and keep the serialiser that touches provider config off every handler that can return JSON.
- Partition shared state by tenant. Cache keys, vector namespaces, and log views all include the tenant ID, and that ID comes from the authenticated session server-side — never from a request field.
- Strip identity headers at the proxy.
X-Forwarded-Userand friends should be deleted inbound and set only by your own edge. - Alert on key-rotation and config-change events. These are rare, high-signal, and the first thing an attacker does after a bypass.
One clarification that matters: rate limits and quotas are cost controls, not authorization controls. Per-tenant token budgets stop overspend; they do not stop tenant B from reading tenant A's data. Authorization on the gateway is a separate layer you have to build on purpose.
What I confirmed vs. what I did not test
Confirmed: the report coverage and dates from the source material listed above, and the gateway architecture described here, which I have seen in production deployments.
Not tested: the specific unnamed gateway in the Infosecurity warning, its routes, its version range, whether any of these flaws were exploited in the wild, and the organisational specifics behind the claim that AI agents reached production systems. The scanner and probes here are the method; running them against your own deployment is what produces a confirmed result.
Further Reading
- Quartz, 2026-10-15 — coverage of the Semperis report on AI use in most ransomware attacks and staff threats.
- GBHackers News, 2026-10-15 — coverage citing the 84% figure and identity infrastructure under attack.
- SC Media, 2026-10-14 — report on AI agents breaching production systems to spread malware.
- Infosecurity Magazine, 2026-10-15 — warning over high-risk vulnerabilities in a widely used LLM gateway tool.
- OWASP Top 10 for LLM Applications — reference for gateway-adjacent risks like insecure output handling and excessive agency.
- OWASP API Security Project — broken object-level and function-level authorization, which is exactly what Audit 1 and Audit 3 exercise.
These items were surfaced via Google News aggregation; where only an aggregator redirect was available, I have named the publisher and date rather than fabricate a canonical article URL.


