TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { describe, it, expect } from "vitest";2import { isPrivateIp, isPrivateIpv6, isBlockedHostname, checkEndpointUrlSync, privateEndpointsAllowed } from "@/lib/endpoints/ssrf";34describe("SSRF guard — IP ranges", () => {5 it("flags private, loopback, link-local and special IPv4 ranges", () => {6 for (const ip of ["127.0.0.1", "10.0.0.5", "172.16.0.1", "172.31.255.254", "192.168.1.10", "169.254.169.254", "0.0.0.0", "100.64.1.1", "224.0.0.1", "255.255.255.255", "198.18.0.1"]) expect(isPrivateIp(ip), ip).toBe(true);7 for (const ip of ["8.8.8.8", "1.1.1.1", "172.32.0.1", "172.15.0.1", "51.161.112.61", "100.63.255.255"]) expect(isPrivateIp(ip), ip).toBe(false);8 });9 it("flags IPv6 loopback, unique-local, link-local and mapped IPv4", () => {10 for (const ip of ["::1", "::", "fc00::1", "fd12:3456::1", "fe80::1", "fe80::1%en0", "::ffff:127.0.0.1", "::ffff:10.0.0.1", "::ffff:c0a8:0101", "64:ff9b::7f00:1", "ff02::1"]) expect(isPrivateIpv6(ip), ip).toBe(true);11 for (const ip of ["2607:5300:22a:4500::1", "2001:4860:4860::8888", "::ffff:8.8.8.8"]) expect(isPrivateIpv6(ip), ip).toBe(false);12 expect(isPrivateIp("not-an-ip")).toBe(false);13 });14 it("blocks local-only hostnames", () => {15 for (const h of ["localhost", "LOCALHOST", "foo.localhost", "mymac.local", "db.internal", "metadata.google.internal", "ollama", "router.lan"]) expect(isBlockedHostname(h), h).toBe(true);16 for (const h of ["api.openai.com", "my-tunnel.trycloudflare.com", "example.com."]) expect(isBlockedHostname(h), h).toBe(false);17 });18});1920describe("SSRF guard — URL check", () => {21 it("rejects private hosts unless explicitly allowed", () => {22 const r = checkEndpointUrlSync("http://localhost:11434/v1", { allowPrivate: false });23 expect(r.ok).toBe(false);24 expect(r.reason).toBe("PRIVATE_HOST");25 expect(r.isPrivate).toBe(true);26 const ip = checkEndpointUrlSync("http://192.168.2.10:8080/v1", { allowPrivate: false });27 expect(ip.ok).toBe(false);28 expect(ip.reason).toBe("PRIVATE_IP");29 const v6 = checkEndpointUrlSync("http://[::1]:1234/v1", { allowPrivate: false });30 expect(v6.ok).toBe(false);31 const allowed = checkEndpointUrlSync("http://localhost:11434/v1", { allowPrivate: true });32 expect(allowed.ok).toBe(true);33 expect(allowed.isPrivate).toBe(true);34 });35 it("accepts public https and rejects other protocols / embedded credentials", () => {36 expect(checkEndpointUrlSync("https://api.together.xyz/v1", { allowPrivate: false })).toMatchObject({ ok: true, isPrivate: false });37 expect(checkEndpointUrlSync("ftp://example.com/v1", { allowPrivate: false }).reason).toBe("BAD_PROTOCOL");38 expect(checkEndpointUrlSync("file:///etc/passwd", { allowPrivate: false }).reason).toBe("BAD_PROTOCOL");39 expect(checkEndpointUrlSync("http://user:pw@example.com/v1", { allowPrivate: false }).reason).toBe("CREDENTIALS_IN_URL");40 expect(checkEndpointUrlSync("not a url", { allowPrivate: false }).reason).toBe("INVALID_URL");41 });42 it("reads ALLOW_PRIVATE_ENDPOINTS", () => {43 const env = (v?: string) => ({ ...(v === undefined ? {} : { ALLOW_PRIVATE_ENDPOINTS: v }) }) as unknown as NodeJS.ProcessEnv;44 expect(privateEndpointsAllowed(env())).toBe(false);45 expect(privateEndpointsAllowed(env("1"))).toBe(true);46 expect(privateEndpointsAllowed(env("true"))).toBe(true);47 expect(privateEndpointsAllowed(env("0"))).toBe(false);48 });49});50