From 01582816ed892a9d0a02d1eddda44dd85b3ee128 Mon Sep 17 00:00:00 2001 From: failsafesecurity Date: Wed, 8 Apr 2026 16:25:37 -0700 Subject: [PATCH] fix(security): add 0.0.0.0/8 and 198.18.0.0/15 to SSRF blocklist [MEDIUM] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PRIVATE_NETWORKS blocklist was missing two IANA-reserved ranges: - 0.0.0.0/8 ("This network", RFC 1122) — resolves to localhost on many systems, enabling the same class of attacks as 127.0.0.0/8 - 198.18.0.0/15 (Benchmark testing, RFC 2544) — reserved range that should not be reachable in production Add both ranges and regression tests covering their boundaries and IPv4-mapped IPv6 equivalents. Reported-by: FailSafe Security Researcher Co-Authored-By: Joshua Medvinsky --- nemoclaw/src/blueprint/ssrf.test.ts | 6 ++++++ nemoclaw/src/blueprint/ssrf.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/nemoclaw/src/blueprint/ssrf.test.ts b/nemoclaw/src/blueprint/ssrf.test.ts index 7f55c03a3..653389c94 100644 --- a/nemoclaw/src/blueprint/ssrf.test.ts +++ b/nemoclaw/src/blueprint/ssrf.test.ts @@ -38,6 +38,12 @@ describe("isPrivateIp", () => { "100.64.0.1", // RFC 6598 CGNAT "100.127.255.254", // RFC 6598 CGNAT upper bound "::ffff:100.64.0.1", // IPv4-mapped IPv6 — CGNAT + "0.0.0.0", // RFC 1122 "This network" + "0.255.255.255", // RFC 1122 upper bound + "198.18.0.1", // RFC 2544 benchmark testing + "198.19.255.254", // RFC 2544 upper bound + "::ffff:0.0.0.0", // IPv4-mapped IPv6 — "This network" + "::ffff:198.18.0.1", // IPv4-mapped IPv6 — benchmark ])("detects private IP: %s", (ip) => { expect(isPrivateIp(ip)).toBe(true); }); diff --git a/nemoclaw/src/blueprint/ssrf.ts b/nemoclaw/src/blueprint/ssrf.ts index 7daa3a6da..685624a1b 100644 --- a/nemoclaw/src/blueprint/ssrf.ts +++ b/nemoclaw/src/blueprint/ssrf.ts @@ -10,12 +10,14 @@ interface CidrRange { } const PRIVATE_NETWORKS: CidrRange[] = [ + cidr("0.0.0.0", 8), // "This network" (RFC 1122) — resolves to localhost on many systems cidr("127.0.0.0", 8), cidr("10.0.0.0", 8), cidr("172.16.0.0", 12), cidr("192.168.0.0", 16), cidr("169.254.0.0", 16), cidr("100.64.0.0", 10), // RFC 6598 CGNAT (shared address space) + cidr("198.18.0.0", 15), // Benchmark testing (RFC 2544) cidr6("::1", 128), cidr6("::", 128), cidr6("fc00::", 7),