66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import {
|
|
assertSafeObject,
|
|
createTrustedHtml,
|
|
isPrivateAddress,
|
|
isTrustedHtml,
|
|
secureJsonStringify,
|
|
setSecureCookie,
|
|
unwrapTrustedHtml,
|
|
validateUrl,
|
|
} from "../src/index.ts";
|
|
|
|
describe("@wrnexus/security", () => {
|
|
test("escapes HTML-significant JSON and redacts secrets", () => {
|
|
const json = secureJsonStringify({ html: "</script><img>", token: "secret", count: 1 });
|
|
expect(json).toContain("\\u003c/script\\u003e");
|
|
expect(json).toContain("[REDACTED]");
|
|
expect(json).not.toContain("secret");
|
|
});
|
|
|
|
test("rejects prototype-pollution keys and unsafe URL protocols", () => {
|
|
const unsafe = JSON.parse('{"__proto__":{"admin":true}}');
|
|
expect(() => assertSafeObject(unsafe)).toThrow();
|
|
expect(() => validateUrl("javascript:alert(1)")).toThrow();
|
|
});
|
|
|
|
test("identifies private IP ranges", () => {
|
|
expect(isPrivateAddress("127.0.0.1")).toBe(true);
|
|
expect(isPrivateAddress("10.1.2.3")).toBe(true);
|
|
expect(isPrivateAddress("8.8.8.8")).toBe(false);
|
|
});
|
|
|
|
test("enforces __Host cookie rules", () => {
|
|
const writes: unknown[] = [];
|
|
const ctx = {
|
|
url: new URL("https://example.com"),
|
|
cookies: { set: (...args: unknown[]) => writes.push(args) },
|
|
} as any;
|
|
setSecureCookie(ctx, "__Host-session", "value");
|
|
expect(writes).toHaveLength(1);
|
|
expect(writes[0]).toEqual([
|
|
"__Host-session",
|
|
"value",
|
|
expect.objectContaining({ secure: true, httpOnly: true, path: "/", domain: undefined }),
|
|
]);
|
|
});
|
|
|
|
test("accepts repeated references while still rejecting cycles", () => {
|
|
const shared = { value: 1 };
|
|
expect(() => assertSafeObject({ first: shared, second: shared })).not.toThrow();
|
|
const cyclic: Record<string, unknown> = {};
|
|
cyclic.self = cyclic;
|
|
expect(() => assertSafeObject(cyclic)).toThrow();
|
|
});
|
|
|
|
test("trusted HTML requires an explicit sanitizer policy", () => {
|
|
const value = createTrustedHtml('<p onclick="bad()">Hello</p>', {
|
|
name: "test-policy",
|
|
sanitize: (input) => input.replace(/\s+onclick="[^"]*"/g, ""),
|
|
});
|
|
expect(isTrustedHtml(value)).toBe(true);
|
|
expect(unwrapTrustedHtml(value)).toBe("<p>Hello</p>");
|
|
expect(() => unwrapTrustedHtml({ value: "<b>unsafe</b>" } as any)).toThrow();
|
|
});
|
|
});
|