Kareadita/Kavita · warning · KavitaException
url-https-only
Error message
url-https-only
What it means
Thrown by UrlValidationService.ValidateUrlAsync when the parsed URI's scheme is not https (case-insensitive). Kavita forbids plain http:// (and any non-https scheme) for user-supplied URLs as part of its SSRF/transport-security posture. It is a localized KavitaException surfaced as HTTP 500 (or 400 where callers catch it).
Source
Thrown at Kavita.Services/UrlValidationService.cs:22
using System.Threading.Tasks;
using Kavita.API.Services;
using Kavita.Common;
using Kavita.Common.Helpers;
namespace Kavita.Services;
public class UrlValidationService(ILocalizationService localizationService) : IUrlValidationService
{
public async Task ValidateUrlAsync(string url)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
throw new KavitaException(await localizationService.TranslateAsync("url-malformed"));
}
if (!string.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
{
throw new KavitaException(await localizationService.TranslateAsync("url-https-only"));
}
IPAddress[] addresses;
try
{
addresses = await Dns.GetHostAddressesAsync(uri.Host);
}
catch (SocketException)
{
throw new KavitaException(await localizationService.TranslateAsync("url-unable-to-resolve"));
}
if (addresses.Length == 0)
{
throw new KavitaException(await localizationService.TranslateAsync("url-unable-to-resolve"));
}
foreach (var address in addresses)View on GitHub (pinned to 9c3e540000)
Solutions
- Upgrade the URL to https:// on the client before submitting when the target supports TLS.
- Reject non-https input in the form (`new URL(url).protocol === 'https:'`).
- If the target truly has no TLS, host the asset on an https endpoint (e.g., put it behind Kavita's own TLS or a reverse proxy).
Example fix
// before
const url = input; // user may type http://
// after
let url = input.trim();
if (url.startsWith('http://')) url = 'https://' + url.slice('http://'.length); Defensive patterns
Strategy: validation
Validate before calling
function isHttpsUrl(url: string): boolean {
try { return new URL(url.trim()).protocol === 'https:'; } catch { return false; }
} Type guard
function isHttpsString(s: unknown): s is string {
return typeof s === 'string' && isHttpsUrl(s);
} Try / catch
try { await svc.fetchFromUrl(url); } catch (e) { if (/https/i.test(e.message)) showUser('Only https:// URLs are allowed'); else throw e; } Prevention
- Default new URL inputs to https://.
- Upgrade http:// to https:// on the client when the target supports TLS.
- Reject non-https schemes in form validation.
When it happens
Trigger: ValidateUrlAsync receives an absolute URI whose scheme is http, ftp, file, etc. Reachable from all the same callers as error 195 (cover/favicon/font/CBL/upload-by-url).
Common situations: User pastes an http:// image host; a self-hosted resource is only reachable over http; a config field defaulted to http; an internal service without TLS is referenced.
Related errors
- url-malformed
- url-unable-to-resolve
- url-blocked-address
- url-blocked-address
- {comparison} is not applicable for {fieldName}
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/9bd9087bc382bf1c.
Report an issue: GitHub.