Kareadita/Kavita · error · KavitaException
url-blocked-address
Error message
url-blocked-address
What it means
Thrown by FlurlConfiguration.CreateSafeRequest's ConnectCallback after every resolved IP for the target host was either blocked by IpBlocklist (loopback, private, reserved, CGNAT, link-local, multicast ranges) or failed its TCP connect. This is Kavita's SSRF guard preventing requests to internal/private addresses, so it surfaces as HTTP 500 with 'url-blocked-address'.
Source
Thrown at Kavita.Common/Helpers/FlurlConfiguration.cs:88
foreach (var addr in addresses)
{
if (IpBlocklist.IsBlockedAddress(addr)) continue;
var socket = new Socket(addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
await socket.ConnectAsync(new IPEndPoint(addr, context.DnsEndPoint.Port), ct);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
continue;
}
}
throw new KavitaException("url-blocked-address");
}
};
var httpClient = new HttpClient(handler);
client = new FlurlClient(httpClient);
SafeClients[key] = client;
}
return client.Request(url);
}
}
}
View on GitHub (pinned to 9c3e540000)
Solutions
- Use a public hostname/IP that resolves to a routable address — the blocklist rejects private ranges by design.
- If you control the source data, validate the URL is public before handing it to CreateSafeRequest.
- If the target is legitimately internal and trusted, use ConfigureClientForUrl (no SSRF check) only for hardcoded trusted hosts, never user input.
- Fix the target host connectivity if the real problem is refused connections rather than blocked IPs.
Example fix
// before
var req = FlurlConfiguration.CreateSafeRequest("http://192.168.1.5/cover.jpg");
// after
var req = FlurlConfiguration.CreateSafeRequest("https://cdn.example.com/cover.jpg"); Defensive patterns
Strategy: try-catch
Validate before calling
var uri = new Uri(url);
foreach (var addr in await Dns.GetHostAddressesAsync(uri.Host))
if (IpBlocklist.IsBlockedAddress(addr))
throw new InvalidOperationException("URL resolves to a blocked address"); Try / catch
try { var resp = await FlurlConfiguration.CreateSafeRequest(url).GetAsync(); }
catch (KavitaException ex) when (ex.Message == "url-blocked-address")
{ /* surface to user: pick a public URL */ } Prevention
- Only feed public, routable URLs into CreateSafeRequest.
- Pre-validate URLs server-side with IpBlocklist before the request.
- Reserve ConfigureClientForUrl (no SSRF check) for hardcoded trusted hosts only.
When it happens
Trigger: A user-supplied or external URL resolves only to private/reserved IPs (e.g. 127.0.0.1, 10.x, 192.168.x, ::1), or DNS rebinding points a public hostname at an internal IP, or every resolved address refused the connection. Triggered by cover upload-by-url, any Flurl CreateSafeRequest call against such a host.
Common situations: Testing against localhost/lan URLs; a misconfigured cover/book image URL that points at an internal host; DNS rebinding attack; the target host is genuinely unreachable (all IPs fail connect) so the blocklist-or-connect loop exhausts.
Related errors
- url-unable-to-resolve
- url-blocked-address
- invalid-filename
- font-url-not-allowed
- Kavita has already tried to fetch from {sanitizedBaseUrl} an
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/22a0c648d91cdfa5.
Report an issue: GitHub.