zed-industries/zed · error
OAuth endpoint must not point to private/reserved IP: ::ffff
Error message
OAuth endpoint must not point to private/reserved IP: ::ffff:{} What it means
IPv4-mapped IPv6 addresses (::ffff:a.b.c.d) embed an IPv4 address and would otherwise slip past the plain-IPv4 checks in validate_oauth_url. The source explicitly converts the IPv6 host with to_ipv4_mapped() and re-runs the private/link-local/broadcast/unspecified checks on the embedded IPv4 value, bailing with the ::ffff: prefix in the message. Hitting this error means the endpoint URL tried the mapped form of a blocked internal IPv4 address.
Source
Thrown at crates/context_server/src/oauth.rs:99
// Loopback is already allowed by require_https_or_loopback.
if ip.is_private() || ip.is_link_local() || ip.is_broadcast() || ip.is_unspecified()
{
bail!(
"OAuth endpoint must not point to private/reserved IP: {}",
ip
);
}
}
url::Host::Ipv6(ip) => {
// Check for IPv4-mapped IPv6 addresses (::ffff:a.b.c.d) which
// could bypass the IPv4 checks above.
if let Some(mapped_v4) = ip.to_ipv4_mapped() {
if mapped_v4.is_private()
|| mapped_v4.is_link_local()
|| mapped_v4.is_broadcast()
|| mapped_v4.is_unspecified()
{
bail!(
"OAuth endpoint must not point to private/reserved IP: ::ffff:{}",
mapped_v4
);
}
}
if ip.is_unspecified() || ip.is_multicast() {
bail!(
"OAuth endpoint must not point to reserved IPv6 address: {}",
ip
);
}
// IPv6 Unique Local Addresses (fc00::/7). is_unique_local() is
// nightly-only, so check the prefix manually.
if (ip.segments()[0] & 0xfe00) == 0xfc00 {
bail!(
"OAuth endpoint must not point to IPv6 unique-local address: {}",
ipView on GitHub (pinned to f4178619ac)
Solutions
- Use the endpoint's public DNS name over HTTPS instead of any IP-literal form
- If testing locally, use http://localhost or http://127.0.0.1 directly rather than their mapped-IPv6 equivalents
- When fuzzing/reviewing an MCP server, treat this exact message as a blocked SSRF bypass attempt, not a bug in Zed
Example fix
// before
Url::parse("https://[::ffff:10.0.0.5]:9443/token")
// after
Url::parse("https://auth.example.com/token") Defensive patterns
Strategy: validation
Validate before calling
use url::Url;
fn mapped_ipv4_host_allowed(url: &Url) -> bool {
match url.host() {
Some(url::Host::Ipv6(ip)) => match ip.to_ipv4_mapped() {
Some(v4) => {
!(v4.is_private() || v4.is_link_local() || v4.is_broadcast() || v4.is_unspecified())
}
None => true,
},
_ => true,
}
}
if !mapped_ipv4_host_allowed(&endpoint) {
bail_user_config!("endpoint uses IPv4-mapped private address: {}", endpoint);
} Type guard
fn is_allowed_ipv6_literal(url: &Url) -> Option<bool> {
match url.host() {
Some(url::Host::Ipv6(ip)) => Some(
ip.to_ipv4_mapped()
.map(|v4| !(v4.is_private() || v4.is_link_local() || v4.is_broadcast() || v4.is_unspecified()))
.unwrap_or(true),
),
_ => None,
}
} Try / catch
match validate_oauth_url(&endpoint) {
Err(err) if err.to_string().contains("::ffff:") => {
// mapped-IPv6 bypass attempt — reject and audit the source metadata
audit_ssrf_attempt(&endpoint);
Err(err)
}
other => other,
} Prevention
- Normalize all endpoint URLs to domain names in your metadata so no IP-literal forms (v4, mapped-v6, ULA) ever appear
- Include mapped-IPv6 and ULA literals in your own server-side URL linting; naive blocklists miss them
- Treat any partner metadata containing ::ffff: literals as hostile until proven otherwise
When it happens
Trigger: An endpoint URL whose host is an IPv6 literal in the ::ffff:0:0/96 range whose mapped IPv4 is private, link-local, broadcast, or unspecified — e.g. https://[::ffff:192.168.1.10]/token or https://[::ffff:169.254.169.254]/latest/meta-data.
Common situations: Dual-stack servers or test harnesses that normalize IPv4 hosts into mapped-IPv6 form; deliberate bypass attempts where a malicious MCP server encodes a cloud-metadata or LAN address as ::ffff:169.254.169.254 to evade naive blocklists; tools that emit mapped addresses when a hostname resolves to both A and AAAA records.
Related errors
- OAuth endpoint must not point to reserved IPv6 address: {}
- OAuth endpoint must not point to IPv6 unique-local address:
- OAuth endpoint must not point to private/reserved IP: {}
- OAuth endpoint must use HTTPS (got {}://{})
- WWW-Authenticate header does not use Bearer scheme
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/3e60ea2720544188.
Report an issue: GitHub.