v0.4.108 - SSRF DNS-resolution fix + mandatory HTTP allowlist
Security release
Fixes GHSA-798p-78g2-v556 (CWE-918 SSRF). validateServerUrl previously
validated only the hostname string, so a name that resolves to an internal
IP (e.g. lvh.me → 127.0.0.1, *.nip.io → cloud IMDS 169.254.169.254)
bypassed the guard. A string denylist cannot close this class.
Changes
- DNS resolution now backs the guard for every Node request: the SSRF-safe
lookupagent resolves the hostname, rejects if any resolved IP is
private/internal, and pins the connection to the validated IP — closing
DNS-rebinding and redirect-to-internal.maxRedirectscapped at 5. sparql_query(fetch-based) gets a pre-resolution check (HTTPS-only).- Extracted
isBlockedIp, shared by the literal and resolved-IP guards. - Hardening: the network-exposed HTTP transport refuses to start without
CKAN_ALLOWED_DOMAINS(default-deny), unlessCKAN_HTTP_ALLOW_ALL=true
(logs a warning). stdio is unaffected — any portal can still be queried locally. - 11 new tests; verified end-to-end against a real HTTP deployment.
Not affected
- The official Cloudflare Worker endpoint: the CF sandbox already blocks
loopback/RFC-1918/IMDS.
Reported by: @EchoSkorJjj
Full Changelog: v0.4.107...v0.4.108