Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

36 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { CONTENT_SECURITY_POLICY, makeNonce, pagePolicy, secure } from "./guard.ts";
5
6function directives(policy: string): Map<string, string> {
7 return new Map(policy.split("; ").map((part) => [part.split(" ")[0]!, part]));
8}
9
10test("a page runs only sudo's own scripts, by its nonce", () => {
11 const nonce = makeNonce();
12 assert.match(nonce, /^[A-Za-z0-9+/]{22}==$/);
13 assert.notEqual(nonce, makeNonce());
14 const page = directives(pagePolicy(nonce));
15 assert.equal(page.get("script-src"), `script-src 'self' 'nonce-${nonce}'`);
16 assert.equal(page.get("connect-src"), "connect-src 'self'");
17 assert.doesNotMatch(pagePolicy(nonce), /unsafe-|strict-dynamic|https?:|\*/);
18 // Everything else as strict as an answer that is not a page.
19 const rest = directives(CONTENT_SECURITY_POLICY);
20 for (const [name, value] of rest) if (name !== "script-src") assert.equal(page.get(name), value, name);
21 assert.deepEqual([...page.keys()].filter((name) => !rest.has(name)), ["connect-src"]);
22});
23
24test("an answer that is not a page runs nothing", () => {
25 assert.equal(directives(CONTENT_SECURITY_POLICY).get("script-src"), "script-src 'none'");
26 assert.equal(directives(CONTENT_SECURITY_POLICY).get("default-src"), "default-src 'none'");
27});
28
29test("a page keeps its own policy; anything else gets the strict one", () => {
30 const nonce = makeNonce();
31 const page = secure(new Response("<html></html>", { headers: { "content-security-policy": pagePolicy(nonce) } }));
32 assert.equal(page.headers.get("content-security-policy"), pagePolicy(nonce));
33 assert.equal(page.headers.get("cache-control"), "no-store");
34 const data = secure(new Response("{}"));
35 assert.equal(data.headers.get("content-security-policy"), CONTENT_SECURITY_POLICY);
36});