import { describe, it, expect } from "vitest"; import { isPrivateAddress } from "../validate-webhook-url"; describe("isPrivateAddress", () => { it("flags IPv4 private/reserved ranges", () => { expect(isPrivateAddress("127.0.0.1")).toBe(true); expect(isPrivateAddress("10.1.2.3")).toBe(true); expect(isPrivateAddress("172.16.0.1")).toBe(true); expect(isPrivateAddress("192.168.1.1")).toBe(true); expect(isPrivateAddress("169.254.1.1")).toBe(true); expect(isPrivateAddress("224.0.0.1")).toBe(true); }); it("allows public IPv4 addresses", () => { expect(isPrivateAddress("8.8.8.8")).toBe(false); expect(isPrivateAddress("1.1.1.1")).toBe(false); }); it("fails closed on malformed IPv4 octets", () => { expect(isPrivateAddress("999.999.999.999")).toBe(true); }); it("flags IPv6 loopback and unspecified addresses in any compression form", () => { expect(isPrivateAddress("::1")).toBe(true); expect(isPrivateAddress("::")).toBe(true); expect(isPrivateAddress("0:0:0:0:0:0:0:1")).toBe(true); }); it("flags IPv6 unique-local (fc00::/7) and link-local (fe80::/10) ranges", () => { expect(isPrivateAddress("fc00::1")).toBe(true); expect(isPrivateAddress("fd12:3456::1")).toBe(true); expect(isPrivateAddress("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")).toBe(true); expect(isPrivateAddress("fe80::1")).toBe(true); expect(isPrivateAddress("fe00::1")).toBe(false); }); it("recurses into IPv4-mapped IPv6 addresses, including non-compressed forms", () => { expect(isPrivateAddress("::ffff:127.0.0.1")).toBe(true); expect(isPrivateAddress("::ffff:10.0.0.5")).toBe(true); expect(isPrivateAddress("::ffff:8.8.8.8")).toBe(false); }); it("fails closed on a malformed IPv4-mapped address (out-of-range octets)", () => { expect(isPrivateAddress("::ffff:999.999.999.999")).toBe(true); }); it("allows public IPv6 addresses", () => { expect(isPrivateAddress("2001:4860:4860::8888")).toBe(false); }); it("fails closed on unparseable input", () => { expect(isPrivateAddress("not-an-ip")).toBe(true); }); });