Created
December 9, 2021 12:57
-
-
Save dumkydewilde/fe7281b0c0cafbf68b5c4d4c59bdb567 to your computer and use it in GitHub Desktop.
Use Cloudflare Workers to inject CSP headers in your requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const NONCE_SECRET = "S3CR3T" // Identify where to inject nonces in your page | |
class ElementHandler { | |
constructor(generatedNonce, nonceReplaceValue) { | |
this.generatedNonce = generatedNonce | |
this.nonceReplaceValue = nonceReplaceValue | |
} | |
element(element) { | |
// An incoming element, such as `div` | |
console.log(`Incoming element: ${element.tagName}`) | |
if (element.getAttribute('nonce') === this.nonceReplaceValue) { | |
element.setAttribute('nonce', this.generatedNonce); | |
} | |
if (element.getAttribute('data-nonce') === this.nonceReplaceValue) { | |
element.setAttribute('data-nonce', this.generatedNonce); | |
} | |
} | |
} | |
async function adjustHeaders(response, setHeaders, removeHeaders) { | |
let newHeaders = new Headers(response.headers) | |
if (newHeaders.has("Content-Type") && !newHeaders.get("Content-Type").includes("text/html")) { | |
return new Response(response.body, { | |
status: response.status, | |
statusText: response.statusText, | |
headers: newHeaders | |
}); | |
} | |
Object.keys(setHeaders).forEach(name => newHeaders.set(name, setHeaders[name])); | |
removeHeaders.forEach(name => newHeaders.delete(name)); | |
return new Response(response.body, { | |
status: response.status, | |
statusText: response.statusText, | |
headers: newHeaders | |
}); | |
} | |
async function handleRequest(req) { | |
try { | |
const res = await fetch(req) | |
const generatedNonce = btoa(crypto.getRandomValues(new Uint32Array(2))) | |
const CSP_POLICY = `default-src 'self';` + | |
`style-src 'self' 'unsafe-inline';` + | |
`script-src 'self' 'nonce-${generatedNonce}' https://gtm.dumky.net https://unpkg.com https://www.googletagmanager.com https://www.google-analytics.com/;` + | |
`connect-src 'self' 'nonce-${generatedNonce}' https://www.google-analytics.com;` + | |
`img-src 'self' 'nonce-${generatedNonce}' https://www.google-analytics.com;`; | |
const setHeaders = { | |
"Content-Security-Policy" : CSP_POLICY, | |
"Referrer-Policy" : "strict-origin-when-cross-origin" | |
} | |
const removeHeaders = []; | |
const rewriter = new HTMLRewriter(); | |
rewriter.on("script", new ElementHandler(generatedNonce, NONCE_SECRET)); | |
//return adjustHeaders(res, setHeaders, removeHeaders) | |
return adjustHeaders(rewriter.transform(res), setHeaders, removeHeaders) | |
} catch(e) { | |
console.error(e) | |
} | |
} | |
addEventListener("fetch", event => { | |
event.respondWith(handleRequest(event.request)) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment