test: optimize gateway infra memory and security coverage

This commit is contained in:
Peter Steinberger
2026-02-21 21:43:20 +00:00
parent 58254b3b57
commit cc2ff68947
24 changed files with 1163 additions and 1284 deletions

View File

@@ -15,37 +15,22 @@ function okResponse(body = "ok"): Response {
describe("fetchWithSsrFGuard hardening", () => {
type LookupFn = NonNullable<Parameters<typeof fetchWithSsrFGuard>[0]["lookupFn"]>;
it("blocks private IP literal URLs before fetch", async () => {
const fetchImpl = vi.fn();
await expect(
fetchWithSsrFGuard({
url: "http://127.0.0.1:8080/internal",
fetchImpl,
}),
).rejects.toThrow(/private|internal|blocked/i);
expect(fetchImpl).not.toHaveBeenCalled();
});
it("blocks legacy loopback literal URLs before fetch", async () => {
const fetchImpl = vi.fn();
await expect(
fetchWithSsrFGuard({
url: "http://0177.0.0.1:8080/internal",
fetchImpl,
}),
).rejects.toThrow(/private|internal|blocked/i);
expect(fetchImpl).not.toHaveBeenCalled();
});
it("blocks unsupported packed-hex loopback literal URLs before fetch", async () => {
const fetchImpl = vi.fn();
await expect(
fetchWithSsrFGuard({
url: "http://0x7f000001/internal",
fetchImpl,
}),
).rejects.toThrow(/private|internal|blocked/i);
expect(fetchImpl).not.toHaveBeenCalled();
it("blocks private and legacy loopback literals before fetch", async () => {
const blockedUrls = [
"http://127.0.0.1:8080/internal",
"http://0177.0.0.1:8080/internal",
"http://0x7f000001/internal",
];
for (const url of blockedUrls) {
const fetchImpl = vi.fn();
await expect(
fetchWithSsrFGuard({
url,
fetchImpl,
}),
).rejects.toThrow(/private|internal|blocked/i);
expect(fetchImpl).not.toHaveBeenCalled();
}
});
it("blocks redirect chains that hop to private hosts", async () => {

View File

@@ -59,27 +59,23 @@ const unsupportedLegacyIpv4Cases = [
const nonIpHostnameCases = ["example.com", "abc.123.example", "1password.com", "0x.example.com"];
describe("ssrf ip classification", () => {
it.each(privateIpCases)("classifies %s as private", (address) => {
expect(isPrivateIpAddress(address)).toBe(true);
});
it.each(publicIpCases)("classifies %s as public", (address) => {
expect(isPrivateIpAddress(address)).toBe(false);
});
it.each(malformedIpv6Cases)("fails closed for malformed IPv6 %s", (address) => {
expect(isPrivateIpAddress(address)).toBe(true);
});
it.each(unsupportedLegacyIpv4Cases)(
"fails closed for unsupported legacy IPv4 literal %s",
(address) => {
it("classifies blocked ip literals as private", () => {
const blockedCases = [...privateIpCases, ...malformedIpv6Cases, ...unsupportedLegacyIpv4Cases];
for (const address of blockedCases) {
expect(isPrivateIpAddress(address)).toBe(true);
},
);
}
});
it.each(nonIpHostnameCases)("does not treat hostname %s as an IP literal", (hostname) => {
expect(isPrivateIpAddress(hostname)).toBe(false);
it("classifies public ip literals as non-private", () => {
for (const address of publicIpCases) {
expect(isPrivateIpAddress(address)).toBe(false);
}
});
it("does not treat hostnames as ip literals", () => {
for (const hostname of nonIpHostnameCases) {
expect(isPrivateIpAddress(hostname)).toBe(false);
}
});
});