mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 19:02:17 +03:00
parseAndValidateWebhookUrl only classified the literal hostname STRING, so a webhook host an attacker controls (DNS pointed at 169.254.169.254 or an RFC1918 address) passed the guard and reached the real fetch() unmodified. Adds fetchWebhookUrl (src/shared/network/webhookFetch.ts): resolves DNS up front, rejects any resolved answer that is cloud-metadata (always) or private (unless the private-provider-URL opt-in is on), pins the connection to the validated address, and revalidates every redirect hop the same way. Reuses the connection-pinning mechanism already proven in remoteImageFetch.ts (GHSA-cmhj-wh2f-9cgx), extracted into a shared src/shared/network/dnsPinnedFetch.ts module instead of duplicating it. Wires webhookDispatcher.ts (deliverRaw/deliverWebhook) and the webhook test endpoint through the new helper; the test endpoint's response-body redaction now follows the resolved-IP classification instead of the raw hostname string. A guard-blocked delivery fails fast (no retry backoff) since it will keep resolving the same way.