Files
story/test/tencent-captcha-csp.test.mjs
T

33 lines
1.8 KiB
JavaScript
Raw Normal View History

import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { test } from 'node:test';
const config = readFileSync(process.env.CAPTCHA_NGINX_CONFIG ?? new URL('../deploy/web.nginx.conf', import.meta.url), 'utf8');
const headers = [...config.matchAll(/add_header\s+Content-Security-Policy\s+"([^"]+)"\s+always/g)];
assert.ok(headers.length, 'HTML must retain an enforced Content-Security-Policy');
const policies = headers.map(([, header]) => new Map(header.split(';').map(value => value.trim().split(/\s+/)).filter(([name]) => name).map(([name, ...sources]) => [name, sources])));
test('Tencent CAPTCHA entry, secondary scripts and styles are allowed', () => {
for (const policy of policies) {
for (const host of ['https://turing.captcha.qcloud.com', 'https://turing.captcha.gtimg.com']) {
assert.ok(policy.get('script-src')?.includes(host), `${host} must be allowed for scripts`);
assert.ok(policy.get('style-src')?.includes(host), `${host} must be allowed for styles`);
}
}
});
test('CAPTCHA blob workers are permitted without allowing blob scripts', () => {
for (const policy of policies) {
assert.deepEqual(policy.get('worker-src'), ["'self'", 'blob:']);
assert.ok(!policy.get('script-src')?.includes('blob:'));
}
});
test('strict script and document protections remain in force', () => {
const allowedScripts = new Set(["'self'", 'https://turing.captcha.gtimg.com', 'https://turing.captcha.qcloud.com', 'https://ssl.captcha.qq.com']);
for (const policy of policies) {
assert.ok(policy.get('script-src')?.every(source => allowedScripts.has(source)), 'no inline/eval or broad script wildcards');
assert.deepEqual(policy.get('default-src'), ["'self'"]);
assert.deepEqual(policy.get('frame-ancestors'), ["'none'"]);
assert.deepEqual(policy.get('base-uri'), ["'self'"]);
}
});