test: simplify trusted proxy coverage

This commit is contained in:
Peter Steinberger 2026-03-13 17:52:49 +00:00
parent 87c447ed46
commit 118abfbdb7
1 changed files with 141 additions and 111 deletions

View File

@ -49,117 +49,147 @@ describe("isLocalishHost", () => {
});
describe("isTrustedProxyAddress", () => {
describe("exact IP matching", () => {
it("returns true when IP matches exactly", () => {
expect(isTrustedProxyAddress("192.168.1.1", ["192.168.1.1"])).toBe(true);
});
it("returns false when IP does not match", () => {
expect(isTrustedProxyAddress("192.168.1.2", ["192.168.1.1"])).toBe(false);
});
it("returns true when IP matches one of multiple proxies", () => {
expect(isTrustedProxyAddress("10.0.0.5", ["192.168.1.1", "10.0.0.5", "172.16.0.1"])).toBe(
true,
);
});
it("ignores surrounding whitespace in exact IP entries", () => {
expect(isTrustedProxyAddress("10.0.0.5", [" 10.0.0.5 "])).toBe(true);
});
});
describe("CIDR subnet matching", () => {
it("returns true when IP is within /24 subnet", () => {
expect(isTrustedProxyAddress("10.42.0.59", ["10.42.0.0/24"])).toBe(true);
expect(isTrustedProxyAddress("10.42.0.1", ["10.42.0.0/24"])).toBe(true);
expect(isTrustedProxyAddress("10.42.0.254", ["10.42.0.0/24"])).toBe(true);
});
it("returns false when IP is outside /24 subnet", () => {
expect(isTrustedProxyAddress("10.42.1.1", ["10.42.0.0/24"])).toBe(false);
expect(isTrustedProxyAddress("10.43.0.1", ["10.42.0.0/24"])).toBe(false);
});
it("returns true when IP is within /16 subnet", () => {
expect(isTrustedProxyAddress("172.19.5.100", ["172.19.0.0/16"])).toBe(true);
expect(isTrustedProxyAddress("172.19.255.255", ["172.19.0.0/16"])).toBe(true);
});
it("returns false when IP is outside /16 subnet", () => {
expect(isTrustedProxyAddress("172.20.0.1", ["172.19.0.0/16"])).toBe(false);
});
it("returns true when IP is within /32 subnet (single IP)", () => {
expect(isTrustedProxyAddress("10.42.0.0", ["10.42.0.0/32"])).toBe(true);
});
it("returns false when IP does not match /32 subnet", () => {
expect(isTrustedProxyAddress("10.42.0.1", ["10.42.0.0/32"])).toBe(false);
});
it("handles mixed exact IPs and CIDR notation", () => {
const proxies = ["192.168.1.1", "10.42.0.0/24", "172.19.0.0/16"];
expect(isTrustedProxyAddress("192.168.1.1", proxies)).toBe(true); // exact match
expect(isTrustedProxyAddress("10.42.0.59", proxies)).toBe(true); // CIDR match
expect(isTrustedProxyAddress("172.19.5.100", proxies)).toBe(true); // CIDR match
expect(isTrustedProxyAddress("10.43.0.1", proxies)).toBe(false); // no match
});
it("supports IPv6 CIDR notation", () => {
expect(isTrustedProxyAddress("2001:db8::1234", ["2001:db8::/32"])).toBe(true);
expect(isTrustedProxyAddress("2001:db9::1234", ["2001:db8::/32"])).toBe(false);
});
});
describe("backward compatibility", () => {
it("preserves exact IP matching behavior (no CIDR notation)", () => {
// Old configs with exact IPs should work exactly as before
expect(isTrustedProxyAddress("192.168.1.1", ["192.168.1.1"])).toBe(true);
expect(isTrustedProxyAddress("192.168.1.2", ["192.168.1.1"])).toBe(false);
expect(isTrustedProxyAddress("10.0.0.5", ["192.168.1.1", "10.0.0.5"])).toBe(true);
});
it("does NOT treat plain IPs as /32 CIDR (exact match only)", () => {
// "10.42.0.1" without /32 should match ONLY that exact IP
expect(isTrustedProxyAddress("10.42.0.1", ["10.42.0.1"])).toBe(true);
expect(isTrustedProxyAddress("10.42.0.2", ["10.42.0.1"])).toBe(false);
expect(isTrustedProxyAddress("10.42.0.59", ["10.42.0.1"])).toBe(false);
});
it("handles IPv4-mapped IPv6 addresses (existing normalizeIp behavior)", () => {
// Existing normalizeIp() behavior should be preserved
expect(isTrustedProxyAddress("::ffff:192.168.1.1", ["192.168.1.1"])).toBe(true);
});
});
describe("edge cases", () => {
it("returns false when IP is undefined", () => {
expect(isTrustedProxyAddress(undefined, ["192.168.1.1"])).toBe(false);
});
it("returns false when trustedProxies is undefined", () => {
expect(isTrustedProxyAddress("192.168.1.1", undefined)).toBe(false);
});
it("returns false when trustedProxies is empty", () => {
expect(isTrustedProxyAddress("192.168.1.1", [])).toBe(false);
});
it("returns false for invalid CIDR notation", () => {
expect(isTrustedProxyAddress("10.42.0.59", ["10.42.0.0/33"])).toBe(false); // invalid prefix
expect(isTrustedProxyAddress("10.42.0.59", ["10.42.0.0/-1"])).toBe(false); // negative prefix
expect(isTrustedProxyAddress("10.42.0.59", ["invalid/24"])).toBe(false); // invalid IP
});
it("ignores surrounding whitespace in CIDR entries", () => {
expect(isTrustedProxyAddress("10.42.0.59", [" 10.42.0.0/24 "])).toBe(true);
});
it("ignores blank trusted proxy entries", () => {
expect(isTrustedProxyAddress("10.0.0.5", [" ", "\t"])).toBe(false);
expect(isTrustedProxyAddress("10.0.0.5", [" ", "10.0.0.5", ""])).toBe(true);
});
it.each([
{
name: "matches exact IP entries",
ip: "192.168.1.1",
trustedProxies: ["192.168.1.1"],
expected: true,
},
{
name: "rejects non-matching exact IP entries",
ip: "192.168.1.2",
trustedProxies: ["192.168.1.1"],
expected: false,
},
{
name: "matches one of multiple exact entries",
ip: "10.0.0.5",
trustedProxies: ["192.168.1.1", "10.0.0.5", "172.16.0.1"],
expected: true,
},
{
name: "ignores surrounding whitespace in exact IP entries",
ip: "10.0.0.5",
trustedProxies: [" 10.0.0.5 "],
expected: true,
},
{
name: "matches /24 CIDR entries",
ip: "10.42.0.59",
trustedProxies: ["10.42.0.0/24"],
expected: true,
},
{
name: "rejects IPs outside /24 CIDR entries",
ip: "10.42.1.1",
trustedProxies: ["10.42.0.0/24"],
expected: false,
},
{
name: "matches /16 CIDR entries",
ip: "172.19.255.255",
trustedProxies: ["172.19.0.0/16"],
expected: true,
},
{
name: "rejects IPs outside /16 CIDR entries",
ip: "172.20.0.1",
trustedProxies: ["172.19.0.0/16"],
expected: false,
},
{
name: "treats /32 as a single-IP CIDR",
ip: "10.42.0.0",
trustedProxies: ["10.42.0.0/32"],
expected: true,
},
{
name: "rejects non-matching /32 CIDR entries",
ip: "10.42.0.1",
trustedProxies: ["10.42.0.0/32"],
expected: false,
},
{
name: "handles mixed exact IP and CIDR entries",
ip: "172.19.5.100",
trustedProxies: ["192.168.1.1", "10.42.0.0/24", "172.19.0.0/16"],
expected: true,
},
{
name: "rejects IPs missing from mixed exact IP and CIDR entries",
ip: "10.43.0.1",
trustedProxies: ["192.168.1.1", "10.42.0.0/24", "172.19.0.0/16"],
expected: false,
},
{
name: "supports IPv6 CIDR notation",
ip: "2001:db8::1234",
trustedProxies: ["2001:db8::/32"],
expected: true,
},
{
name: "rejects IPv6 addresses outside the configured CIDR",
ip: "2001:db9::1234",
trustedProxies: ["2001:db8::/32"],
expected: false,
},
{
name: "preserves exact matching behavior for plain IP entries",
ip: "10.42.0.59",
trustedProxies: ["10.42.0.1"],
expected: false,
},
{
name: "normalizes IPv4-mapped IPv6 addresses",
ip: "::ffff:192.168.1.1",
trustedProxies: ["192.168.1.1"],
expected: true,
},
{
name: "returns false when IP is undefined",
ip: undefined,
trustedProxies: ["192.168.1.1"],
expected: false,
},
{
name: "returns false when trusted proxies are undefined",
ip: "192.168.1.1",
trustedProxies: undefined,
expected: false,
},
{
name: "returns false when trusted proxies are empty",
ip: "192.168.1.1",
trustedProxies: [],
expected: false,
},
{
name: "rejects invalid CIDR prefixes and addresses",
ip: "10.42.0.59",
trustedProxies: ["10.42.0.0/33", "10.42.0.0/-1", "invalid/24", "2001:db8::/129"],
expected: false,
},
{
name: "ignores surrounding whitespace in CIDR entries",
ip: "10.42.0.59",
trustedProxies: [" 10.42.0.0/24 "],
expected: true,
},
{
name: "ignores blank trusted proxy entries",
ip: "10.0.0.5",
trustedProxies: [" ", "10.0.0.5", ""],
expected: true,
},
{
name: "treats all-blank trusted proxy entries as no match",
ip: "10.0.0.5",
trustedProxies: [" ", "\t"],
expected: false,
},
])("$name", ({ ip, trustedProxies, expected }) => {
expect(isTrustedProxyAddress(ip, trustedProxies)).toBe(expected);
});
});