From 46238dcfedfeb7936ad3ebed99e26f2ade6d3ca4 Mon Sep 17 00:00:00 2001 From: aiirvizionz Date: Sun, 12 Jul 2026 19:57:12 -0600 Subject: [PATCH] Block special-use webhook IPv4 ranges --- lib/url-guard.ts | 2 ++ tests/url-guard.test.mjs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/lib/url-guard.ts b/lib/url-guard.ts index d809325..0ec82d1 100644 --- a/lib/url-guard.ts +++ b/lib/url-guard.ts @@ -45,7 +45,9 @@ export function isInternalUrl(raw: string): boolean { if (a === 127 || a === 10 || a === 0) return true; if (a === 172 && b >= 16 && b <= 31) return true; if (a === 192 && b === 168) return true; + if (a === 100 && b >= 64 && b <= 127) return true; if (a === 169 && b === 254) return true; + if (a === 198 && (b === 18 || b === 19)) return true; } return false; } diff --git a/tests/url-guard.test.mjs b/tests/url-guard.test.mjs index e53aa27..10f0016 100644 --- a/tests/url-guard.test.mjs +++ b/tests/url-guard.test.mjs @@ -11,6 +11,13 @@ test("SSRF guard blocks private IPv6 webhook targets", () => { assert.equal(isInternalUrl("http://[::ffff:192.168.1.10]/hook"), true); }); +test("SSRF guard blocks internal IPv4 special-use ranges", () => { + assert.equal(isInternalUrl("http://100.64.0.1/hook"), true); + assert.equal(isInternalUrl("http://100.127.255.254/hook"), true); + assert.equal(isInternalUrl("http://198.18.0.1/hook"), true); + assert.equal(isInternalUrl("http://198.19.255.254/hook"), true); +}); + test("SSRF guard allows public IPv6 webhook targets", () => { assert.equal(isInternalUrl("https://[2606:4700:4700::1111]/hook"), false); assert.equal(isInternalUrl("https://[::ffff:8.8.8.8]/hook"), false);