test.build/core/validators/security.validator.test.ts
test.build/core/validators/security.validator.test.ts is a file in Codebase Testing. 80 lines of code and 0 definitions.
import { type TestKey, testKey } from "../adapters/security.fixture.ts";
import {
UNSIGNED_SECURITY_TXT,
WANTED_SECURITY_CONTACT,
WANTED_SECURITY_EXPIRY,
malformedSecurityField,
} from "@banes-lab/build-scripts/configuration/strings/site.strings.ts";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import {
checkSecurityTxt,
checkSignature,
securityFindings,
} from "@banes-lab/build-scripts/core/validators/security.validator.ts";
import { MISSING_BUILD_FILE } from "@banes-lab/build-scripts/configuration/strings/validation.strings.ts";
import { signText } from "@banes-lab/build-scripts/core/adapters/security.adapter.ts";
const { BUILT } = vi.hoisted(() => ({ BUILT: new Map<string, string>() }));
vi.mock("@banes-lab/build-scripts/core/loaders/build.loader.ts", async (original) => ({
...(await original<object>()),
readOrNull: (file: string) => BUILT.get(file) ?? null,
}));
const now = new Date("2026-10-08T00:00:00Z");
const site = "https://example.test";
const canonical = `Canonical: ${site}/.well-known/security.txt`;
const encryption = `Encryption: ${site}/.well-known/pgp-key.txt`;
describe("checkSecurityTxt", () => {
it("accepts a mailto contact, its public key, an expiry within a year and its own canonical address", () => {
const text = ["Contact: mailto:a@example.test", encryption, "Expires: 2027-10-01T00:00:00.000Z", canonical].join(
"\n",
);
expect(checkSecurityTxt("s.txt", text, site, now)).toStrictEqual([]);
});
it("reports a missing or foreign public key address", () => {
const text = ["Contact: mailto:a@example.test", "Expires: 2027-10-01T00:00:00.000Z", canonical].join("\n");
expect(checkSecurityTxt("s.txt", text, site, now)).toStrictEqual([
{ file: "s.txt", message: malformedSecurityField("Encryption", "", `${site}/.well-known/pgp-key.txt`) },
]);
});
it("reports a contact without mailto, a lapsed or distant expiry and a foreign canonical", () => {
const lapsed = ["Contact: a@example.test", encryption, "Expires: 2026-01-01T00:00:00.000Z", canonical].join("\n");
expect(checkSecurityTxt("s.txt", lapsed, site, now)).toStrictEqual([
{
file: "s.txt",
message: malformedSecurityField("Contact", "a@example.test", WANTED_SECURITY_CONTACT),
},
{
file: "s.txt",
message: malformedSecurityField("Expires", "2026-01-01T00:00:00.000Z", WANTED_SECURITY_EXPIRY),
},
]);
const distant = ["Contact: mailto:a@example.test", encryption, "Expires: 2028-01-01T00:00:00.000Z"].join("\n");
expect(checkSecurityTxt("s.txt", distant, site, now)).toHaveLength(2);
});
});
describe("checkSignature", () => {
let key: TestKey | null = null;
beforeAll(() => {
key = testKey();
});
afterAll(() => {
key?.dispose();
});
it("passes a text signed by the served key, and reports an unsigned one", () => {
const security = signText(key?.encoded ?? "", `${canonical}\n`);
expect(checkSignature("s.txt", security.signed, security.publicKey)).toStrictEqual([]);
expect(checkSignature("s.txt", `${canonical}\n`, security.publicKey)).toStrictEqual([
{ file: "s.txt", message: UNSIGNED_SECURITY_TXT },
]);
});
it("reads the built security.txt and key, passes a signed file and reports a missing one", () => {
const text = ["Contact: mailto:a@example.test", encryption, "Expires: 2027-10-01T00:00:00.000Z", canonical, ""];
const security = signText(key?.encoded ?? "", text.join("\n"));
BUILT.set(".well-known/security.txt", security.signed);
BUILT.set(".well-known/pgp-key.txt", security.publicKey);
expect(securityFindings(site, now)).toStrictEqual([]);
BUILT.clear();
expect(securityFindings(site, now)).toStrictEqual([
{ file: ".well-known/security.txt", message: MISSING_BUILD_FILE },
]);
});
});