-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheaders-served.test.js
More file actions
74 lines (64 loc) · 2.44 KB
/
Copy pathheaders-served.test.js
File metadata and controls
74 lines (64 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// M1B integration test: security headers are served on a real HTTP response,
// produced from the committed baseline through the hardened response boundary.
// This is in-process evidence only; CDN/edge/browser verification remains open.
import { test, before, after } from 'node:test';
import assert from 'node:assert/strict';
import { createServer } from 'node:http';
import { loadBaseline } from '../../src/security/csp.js';
import {
applyHardenedSecurityHeaders,
buildHardenedHeaderMap,
} from '../../src/security/header-values.js';
let server;
let baseUrl;
const baseline = loadBaseline();
const headerMap = buildHardenedHeaderMap(baseline);
before(async () => {
server = createServer((req, res) => {
applyHardenedSecurityHeaders(res, baseline);
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.statusCode = 200;
res.end('<!doctype html><title>APP-01</title>');
});
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
const { port } = server.address();
baseUrl = `http://127.0.0.1:${port}/`;
});
after(async () => {
await new Promise((resolve) => server.close(resolve));
});
test('served response carries the CSP header equal to the hardened baseline', async () => {
const res = await fetch(baseUrl);
assert.equal(res.status, 200);
assert.equal(
res.headers.get('content-security-policy'),
headerMap['Content-Security-Policy'],
);
});
test('served CSP pins connect-src to self without wildcard or scheme sources', async () => {
const res = await fetch(baseUrl);
const csp = res.headers.get('content-security-policy');
assert.match(csp, /(^|; )connect-src 'self'(;|$)/);
assert.doesNotMatch(csp, /connect-src[^;]*\*/);
assert.doesNotMatch(csp, /connect-src[^;]*\bhttps:/);
});
for (const [name, value] of Object.entries(headerMap)) {
test(`served response carries exact protected header ${name}`, async () => {
const res = await fetch(baseUrl);
assert.equal(res.headers.get(name.toLowerCase()), value);
});
}
test('served response advertises Trusted Types enforcement', async () => {
const res = await fetch(baseUrl);
assert.match(
res.headers.get('content-security-policy'),
/require-trusted-types-for 'script'/,
);
});
test('served Permissions-Policy equals the reviewed committed deny set', async () => {
const res = await fetch(baseUrl);
assert.equal(
res.headers.get('permissions-policy'),
baseline.additional_headers['Permissions-Policy'],
);
});