n8n-io/n8n · error · Error
Webhook URL must use HTTPS. Got: ${url.protocol}
Error message
Webhook URL must use HTTPS. Got: ${url.protocol} What it means
`validateWebhookUrl` parses the `--webhook-url` value with `new URL(...)` and rejects any scheme other than `https:`. The check is the first line of SSRF/transport defense for the webhook result-sender: plaintext `http://` URLs would expose the (signed) payload and HMAC headers to the network. The thrown message echoes the offending protocol so the cause is obvious.
Source
Thrown at packages/@n8n/ai-workflow-builder.ee/evaluations/cli/webhook.ts:115
return true;
}
return false;
}
/**
* Validate webhook URL for security (hostname-based checks only).
* - Must be HTTPS
* - Must not target localhost or private/internal IP addresses (SSRF prevention)
*
* Note: This performs synchronous hostname string validation.
* For full SSRF protection, use validateWebhookUrlWithDns() which also resolves DNS.
*/
export function validateWebhookUrl(webhookUrl: string): void {
const url = new URL(webhookUrl);
if (url.protocol !== 'https:') {
throw new Error(`Webhook URL must use HTTPS. Got: ${url.protocol}`);
}
const hostname = url.hostname.toLowerCase();
if (
hostname === 'localhost' ||
hostname === '127.0.0.1' ||
hostname === '::1' ||
hostname === '[::1]'
) {
throw new Error('Webhook URL cannot target localhost');
}
if (isPrivateIp(hostname)) {
throw new Error('Webhook URL cannot target private/internal IP addresses');
}
const blockedHostnames = ['internal', 'intranet', 'corp', 'private', 'local'];View on GitHub (pinned to 5ac6606e81)
Solutions
- Change the URL scheme to `https://`.
- If the receiver is local-only, put it behind a TLS-terminating proxy or a self-signed cert and use an `https://` URL (and accept that localhost is still blocked separately).
- For development, use a tunnel (ngrok/cloudflared) that exposes your local receiver over HTTPS.
Example fix
// before
validateWebhookUrl('http://hooks.example.com/eval');
// after
validateWebhookUrl('https://hooks.example.com/eval'); Defensive patterns
Strategy: validation
Validate before calling
function assertHttpsWebhook(url: string): void {
let parsed: URL;
try { parsed = new URL(url); } catch { throw new Error(`invalid webhook URL: ${url}`); }
if (parsed.protocol !== 'https:') {
throw new Error(`webhook URL must be https, got ${parsed.protocol}`);
}
}
assertHttpsWebhook(webhookUrl); Prevention
- Make `https://` a required prefix in any config field that stores a webhook URL.
- Run all webhook receivers behind TLS; never keep a plaintext HTTP endpoint 'just for dev'.
- Add a CI lint rule that rejects `http://` webhook URLs in checked-in config.
When it happens
Trigger: Passing `--webhook-url http://example.com/hook` (or any non-https URL) to the eval CLI, or programmatically calling `validateWebhookUrl('http://...')`. The URL parses successfully (so `new URL` does not throw) but `url.protocol` is not `'https:'`.
Common situations: Pointing at a local/test receiver over plain HTTP, a typo (`http:/` vs `https:/`), or a config file that stores the URL without a scheme upgrade after migrating to TLS.
Related errors
- Webhook URL cannot target localhost
- Webhook URL cannot target private/internal IP addresses
- Webhook URL cannot target internal hostname: ${hostname}
- Webhook URL hostname resolves to a private/internal IP addre
- Invalid skill at ${sourceDirectory}: ${errors.join('; ')}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/2b3932b17b96e1ff.
Report an issue: GitHub.