Turning the same first-party reverse proxy into a first-party CSP violation reporting pipeline.
Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS) and data injection attacks. It uses HTTP headers — primarily Content-Security-Policy — to control which resources (scripts, styles, images, and so on) a browser is allowed to load, and to report on URLs that violate the policy. This effectively blocks malicious injections when correctly defined.
We set out to see what it would take to set up CSP enforcement and reporting using Tealium and our new first-party reverse proxy, as a POC. It turned out to be straightforward — we added an Advanced HTTP API endpoint that flattens the report’s nested objects down to a flat set of attributes, and sent all of it to EventDB so we could report on it however we wanted.

Routing reports through the proxy
All it took was this conditional redirect in the Worker function to make https://calebjaquith.com/fwd-csp-reports/report operational as a first-party redirect to our Advanced HTTP API endpoint:
Worker routingif (dir === 'csp-reports') {
remote = "https://collect-eu-central-1.tealiumiq.com/integration/event/services-caleb/csp-violations/iuxe4s"
}
Setting the CSP header itself
We added the CSP header in the same Worker from Posts 1 and 2 of this series, by setting the headers:
Worker header injection// Create a new Headers object to modify response headers
const newHeaders = new Headers(response.headers);
// Reuse previously sent Content-Security-Policy
if (originalResponse.status !== 304) {
// 'strict-dynamic' removes the need for nonce propagation
newHeaders.set("content-security-policy",
`default-src 'self'; style-src https://calebjaquith.com 'unsafe-inline'; img-src https://calebjaquith.com https://*.cdninstagram.com data:; script-src 'nonce-${nonce}' 'unsafe-eval' 'strict-dynamic'; report-uri https://calebjaquith.com/fwd-csp-reports/report;`);
newHeaders.set("content-security-policy-report-only",
`default-src 'self' https://*.usercentrics.eu; style-src https://calebjaquith.com 'unsafe-inline'; img-src https://calebjaquith.com https://*.cdninstagram.com data:; script-src 'nonce-${nonce}' 'unsafe-eval' 'strict-dynamic'; report-uri https://calebjaquith.com/fwd-csp-reports/report;`);
}