fix(security): harden browser SSRF defaults and migrate legacy key

This commit is contained in:
Peter Steinberger
2026-02-24 01:51:44 +00:00
parent 8779b523dc
commit 5eb72ab769
24 changed files with 334 additions and 20 deletions

View File

@@ -154,4 +154,19 @@ describe("ssrf pinning", () => {
});
expect(lookup).toHaveBeenCalledTimes(1);
});
it("accepts dangerouslyAllowPrivateNetwork as an allowPrivateNetwork alias", async () => {
const lookup = vi.fn(async () => [{ address: "127.0.0.1", family: 4 }]) as unknown as LookupFn;
await expect(
resolvePinnedHostnameWithPolicy("localhost", {
lookupFn: lookup,
policy: { dangerouslyAllowPrivateNetwork: true },
}),
).resolves.toMatchObject({
hostname: "localhost",
addresses: ["127.0.0.1"],
});
expect(lookup).toHaveBeenCalledTimes(1);
});
});

View File

@@ -30,6 +30,7 @@ export type LookupFn = typeof dnsLookup;
export type SsrFPolicy = {
allowPrivateNetwork?: boolean;
dangerouslyAllowPrivateNetwork?: boolean;
allowedHostnames?: string[];
hostnameAllowlist?: string[];
};
@@ -60,6 +61,10 @@ function normalizeHostnameAllowlist(values?: string[]): string[] {
);
}
function resolveAllowPrivateNetwork(policy?: SsrFPolicy): boolean {
return policy?.dangerouslyAllowPrivateNetwork === true || policy?.allowPrivateNetwork === true;
}
function isHostnameAllowedByPattern(hostname: string, pattern: string): boolean {
if (pattern.startsWith("*.")) {
const suffix = pattern.slice(2);
@@ -247,7 +252,7 @@ export async function resolvePinnedHostnameWithPolicy(
throw new Error("Invalid hostname");
}
const allowPrivateNetwork = Boolean(params.policy?.allowPrivateNetwork);
const allowPrivateNetwork = resolveAllowPrivateNetwork(params.policy);
const allowedHostnames = normalizeHostnameSet(params.policy?.allowedHostnames);
const hostnameAllowlist = normalizeHostnameAllowlist(params.policy?.hostnameAllowlist);
const isExplicitAllowed = allowedHostnames.has(normalized);