import { describe, expect, it } from "vitest"; import { buildCsp, inspectCsp, inspectHeaders } from "../../src/network/http"; import { lookupMime } from "../../src/network/mime"; describe("HTTP helpers", () => { it("parses duplicates and reports missing security headers", () => { const result = inspectHeaders( "Content-Type: text/html\nSet-Cookie: a=1\nSet-Cookie: b=2", ); expect(result.duplicates).toContain("set-cookie"); expect(result.findings).toContain( "No Content-Security-Policy header is present.", ); }); it("rejects folded headers", () => { expect(() => inspectHeaders("X-Test: one\n two")).toThrow(/folded/u); }); it("builds a restrictive CSP and makes dangerous sources visible", () => { const result = buildCsp({ defaultSrc: "'self'", scriptSrc: "'self' 'unsafe-eval'", styleSrc: "'self'", imgSrc: "'self' data:", connectSrc: "'self'", workerSrc: "'self' blob:", }); expect(result.policy).toContain("object-src 'none'"); expect(result.warnings.join(" ")).toMatch(/unsafe-eval/u); }); it("analyses deployed CSP, cookies, HSTS and framing defenses", () => { const result = inspectHeaders( "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'\n" + "Strict-Transport-Security: max-age=60\n" + "Set-Cookie: session=abc; SameSite=None\n" + "X-Content-Type-Options: nosniff\n" + "Referrer-Policy: strict-origin", ); expect(result.securityFindings.map((finding) => finding.code)).toEqual( expect.arrayContaining([ "csp-unsafe-eval", "hsts-short", "cookie-secure", "cookie-http-only", "cookie-none-insecure", ]), ); expect(result.csp?.directives).toContainEqual({ name: "object-src", values: ["'none'"], }); }); it("identifies duplicate and dangerous CSP directives", () => { const result = inspectCsp( "default-src *; script-src data:; script-src 'self'", ); expect(result.findings.map((finding) => finding.code)).toEqual( expect.arrayContaining([ "csp-wildcard", "csp-script-data", "csp-duplicate-directive", ]), ); }); it("analyses every enforcing CSP field rather than silently dropping later fields", () => { const result = inspectHeaders( "Content-Security-Policy: default-src 'self'; object-src 'none'\n" + "Content-Security-Policy: script-src 'unsafe-eval'; object-src 'none'", ); expect(result.cspFields).toHaveLength(2); expect(result.securityFindings).toContainEqual( expect.objectContaining({ code: "csp-unsafe-eval", message: expect.stringContaining("CSP field 2"), }), ); }); it("uses the first duplicate directive and validates X-Frame-Options", () => { const csp = inspectCsp( "default-src 'self'; object-src *; object-src 'none'", ); expect(csp.findings.map((finding) => finding.code)).toContain( "csp-object-src-open", ); const headers = inspectHeaders( "X-Frame-Options: ALLOW-FROM https://example.test", ); expect(headers.securityFindings.map((finding) => finding.code)).toContain( "x-frame-options-invalid", ); }); it("does not apply sources from ignored duplicate CSP directives", () => { const csp = inspectCsp( "default-src 'self'; script-src 'self'; script-src 'unsafe-eval' data:", ); expect(csp.findings.map((finding) => finding.code)).not.toContain( "csp-unsafe-eval", ); expect(csp.findings.map((finding) => finding.code)).toContain( "csp-duplicate-directive", ); }); }); describe("MIME lookup", () => { it("finds types by extension or media type", () => { expect(lookupMime(".wasm")).toEqual([ { extension: "wasm", mime: "application/wasm" }, ]); expect(lookupMime("epub")[0]?.mime).toBe("application/epub+zip"); }); });