Files
zemion 429b55d587
Verify / verify (push) Canceled after 0s
Release Network Tools 0.2.0
2026-09-02 11:38:57 +02:00

119 lines
3.9 KiB
TypeScript

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");
});
});