koala73/worldmonitor · warning · Error
callbackUrl must use https
Error message
callbackUrl must use https
What it means
Static SSRF-policy check in isBlockedCallbackUrl: after parsing the URL, any protocol other than https: returns 'callbackUrl must use https', rethrown at webhook-shared.ts:121 and surfaced by registerWebhook as a 400 on callbackUrl. Webhook payloads carry a signing secret and partner data, so plaintext http callbacks are rejected outright — there is no opt-out.
Source
Thrown at server/worldmonitor/shipping/v2/webhook-shared.ts:121
return (data.Answer ?? [])
.filter(answer => answer.type === expectedType && typeof answer.data === 'string')
.map(answer => answer.data!);
};
const records = await Promise.all([resolveRecordType('A'), resolveRecordType('AAAA')]);
return records.flat();
}
/**
* Validate the current DNS answer before storing a webhook. Delivery makes the
* same check immediately before send and pins the resulting socket, which
* keeps this fail-fast check from becoming the only SSRF control.
*/
export async function assertCallbackUrlRegistrationSafe(
callbackUrl: string,
resolveHostname: ResolveHostname = defaultResolveHostname,
): Promise<void> {
const staticError = isBlockedCallbackUrl(callbackUrl);
if (staticError) throw new Error(staticError);
const hostname = new URL(callbackUrl).hostname.toLowerCase();
if (isIpLiteral(hostname)) return;
let resolvedAddresses: string[];
try {
resolvedAddresses = await resolveHostname(hostname);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`callbackUrl DNS resolution failed: ${message}`);
}
if (!resolvedAddresses.length) throw new Error('callbackUrl DNS resolution returned no addresses');
const blocked = resolvedAddresses.find(isBlockedResolvedAddress);
if (blocked) throw new Error('callbackUrl resolves to a private/reserved address');
}
export async function generateSecret(): Promise<string> {
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);View on GitHub (pinned to eeab0a219f)
Solutions
- Use an https:// callback URL with a valid TLS certificate on a public host
- For local testing, use a tunnel (for example a localhost https tunnel) to get a real https hostname
- Check the scheme explicitly before submitting: new URL(url).protocol === 'https:'
Example fix
// before
registerWebhook(ctx, { callbackUrl: 'http://api.example.com/cb', chokepointIds });
// after
registerWebhook(ctx, { callbackUrl: 'https://api.example.com/cb', chokepointIds }); Defensive patterns
Strategy: validation
Validate before calling
if (new URL(callbackUrl).protocol !== 'https:') throw new RangeError('callbackUrl must use https'); Type guard
const isHttpsUrl = (v: unknown): v is string => { if (typeof v !== 'string') return false; try { return new URL(v).protocol === 'https:'; } catch { return false; } }; Try / catch
catch (e) { if (e?.details?.[0]?.description === 'callbackUrl must use https') { switch to an https endpoint and re-submit; do not expect an http exception } else throw e; } Prevention
- Provision TLS on callback receivers before registering
- For local dev, use an https tunnel — http callbacks are rejected without exception
- Double-check scheme typos like 'httpss://' which also fail this check
When it happens
Trigger: POST RegisterWebhook with callbackUrl starting 'http://' (including http://localhost or an http intranet host); a URL whose scheme is typo'd ('httpss://') so it fails the equality; mixed local testing against a plain-http dev server.
Common situations: Local dev using http://localhost:3000 as the callback (also independently blocked as a private host); partner endpoints that only expose plain http; scheme defaulted to http by an HTTP client library when building the URL.
Related errors
- callbackUrl is not allowed
- callbackUrl is not a valid URL
- callbackUrl is required
- Unknown chokepoint ID: ${invalidCp}
- alertThreshold must be between 0 and 100
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/624d16a382b8271c.
Report an issue: GitHub.