openvibers/openvibe.search Commits
The CSP allows Cloudflare Web Analytics (browser check, WS-Q task 3): script-src https://static.cloudflareinsights.com loads the beacon Cloudflare injects at the edge, connect-src https://cloudflareinsights.com is where it reports. The network's privacy text already says Cloudflare may measure performance, and Live and Tools allow it; here the policy blocked it and every page view logged a CSP error. Test: page.test.js
Changes
@@@ -18,7 +18,10 @@ const { QueryError, one } = require('../api/query');// The OpenVibe Frame (navbar, footer, "shipped" views, themes) comes from openvibe.network; its init is// /frame-init.js (same origin, no inline script), reading the JSON config in #ov-frame-config.const NETWORK = 'https://openvibe.network';--const CSP = `default-src 'none'; script-src 'self' ${NETWORK}; connect-src 'self' ${NETWORK}; style-src 'unsafe-inline' ${NETWORK}; img-src 'self' data: https:; frame-src ${NETWORK}; form-action 'self' ${NETWORK}; base-uri 'none'; frame-ancestors 'none'`;++// Cloudflare Web Analytics: Cloudflare injects its beacon at the edge and the privacy text says it may measure++// performance; script-src loads the beacon, connect-src is where it reports.++const CF_BEACON = 'https://static.cloudflareinsights.com', CF_REPORT = 'https://cloudflareinsights.com';++const CSP = `default-src 'none'; script-src 'self' ${NETWORK} ${CF_BEACON}; connect-src 'self' ${NETWORK} ${CF_REPORT}; style-src 'unsafe-inline' ${NETWORK}; img-src 'self' data: https:; frame-src ${NETWORK}; form-action 'self' ${NETWORK}; base-uri 'none'; frame-ancestors 'none'`;const frame = require('openvibe-shared/frame');const FRAME_INIT = `(function () {var tries = 0;@@@ -37,7 +37,9 @@ t('the front page is a search form, indexable, no-store, with a strict CSP', asy// The OpenVibe Frame (navbar, footer, shipped views) is the only script: from this site or// openvibe.network, never inline JavaScript (the Frame's config is a JSON data block).const csp = r.headers.get('content-security-policy');-- assert.match(csp, /script-src 'self' https:\/\/openvibe\.network;/);++ // Plus Cloudflare Web Analytics, which Cloudflare injects at the edge (the privacy text discloses it).++ assert.match(csp, /script-src 'self' https:\/\/openvibe\.network https:\/\/static\.cloudflareinsights\.com;/);++ assert.match(csp, /connect-src 'self' https:\/\/openvibe\.network https:\/\/cloudflareinsights\.com;/);assert.ok(!/script-src[^;]*unsafe-inline/.test(csp), 'no inline script allowed');const scripts = [...r.text.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi)];for (const [, attrs, body] of scripts) {
@@ -18,7 +18,10 @@ const { QueryError, one } = require('../api/query');
@@ -18,7 +18,10 @@ const { QueryError, one } = require('../api/query');
// The OpenVibe Frame (navbar, footer, "shipped" views, themes) comes from openvibe.network; its init is
// The OpenVibe Frame (navbar, footer, "shipped" views, themes) comes from openvibe.network; its init is
// /frame-init.js (same origin, no inline script), reading the JSON config in #ov-frame-config.
// /frame-init.js (same origin, no inline script), reading the JSON config in #ov-frame-config.
const NETWORK = 'https://openvibe.network';
const NETWORK = 'https://openvibe.network';
-const CSP = `default-src 'none'; script-src 'self' ${NETWORK}; connect-src 'self' ${NETWORK}; style-src 'unsafe-inline' ${NETWORK}; img-src 'self' data: https:; frame-src ${NETWORK}; form-action 'self' ${NETWORK}; base-uri 'none'; frame-ancestors 'none'`;
+// Cloudflare Web Analytics: Cloudflare injects its beacon at the edge and the privacy text says it may measure
+// performance; script-src loads the beacon, connect-src is where it reports.
+const CF_BEACON = 'https://static.cloudflareinsights.com', CF_REPORT = 'https://cloudflareinsights.com';
+const CSP = `default-src 'none'; script-src 'self' ${NETWORK} ${CF_BEACON}; connect-src 'self' ${NETWORK} ${CF_REPORT}; style-src 'unsafe-inline' ${NETWORK}; img-src 'self' data: https:; frame-src ${NETWORK}; form-action 'self' ${NETWORK}; base-uri 'none'; frame-ancestors 'none'`;
const frame = require('openvibe-shared/frame');
const frame = require('openvibe-shared/frame');
const FRAME_INIT = `(function () {
const FRAME_INIT = `(function () {
var tries = 0;
var tries = 0;
@@ -37,7 +37,9 @@ t('the front page is a search form, indexable, no-store, with a strict CSP', asy
@@ -37,7 +37,9 @@ t('the front page is a search form, indexable, no-store, with a strict CSP', asy
// The OpenVibe Frame (navbar, footer, shipped views) is the only script: from this site or
// The OpenVibe Frame (navbar, footer, shipped views) is the only script: from this site or
// openvibe.network, never inline JavaScript (the Frame's config is a JSON data block).
// openvibe.network, never inline JavaScript (the Frame's config is a JSON data block).
const csp = r.headers.get('content-security-policy');
const csp = r.headers.get('content-security-policy');
- assert.match(csp, /script-src 'self' https:\/\/openvibe\.network;/);
+ // Plus Cloudflare Web Analytics, which Cloudflare injects at the edge (the privacy text discloses it).
+ assert.match(csp, /script-src 'self' https:\/\/openvibe\.network https:\/\/static\.cloudflareinsights\.com;/);
+ assert.match(csp, /connect-src 'self' https:\/\/openvibe\.network https:\/\/cloudflareinsights\.com;/);
assert.ok(!/script-src[^;]*unsafe-inline/.test(csp), 'no inline script allowed');
assert.ok(!/script-src[^;]*unsafe-inline/.test(csp), 'no inline script allowed');
const scripts = [...r.text.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi)];
const scripts = [...r.text.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi)];
for (const [, attrs, body] of scripts) {
for (const [, attrs, body] of scripts) {