Skip to content

Instantly share code, notes, and snippets.

@ematipico
Created April 23, 2025 13:49
Show Gist options
  • Save ematipico/fed39a73f7f94e3f61c868d607a268b2 to your computer and use it in GitHub Desktop.
Save ematipico/fed39a73f7f94e3f61c868d607a268b2 to your computer and use it in GitHub Desktop.

Content Security Policy

There are mostly two solutions that we are looking at:

  • nonce Response header
  • hashes

The nonce header solution

The servrer must create a completely new nonce header at each request (it can't be predictable), and this header needs to be used inside the rendered pages. Example:

function content(nonce) {
  return `
    <script nonce="${nonce}" src="/main.js"></script>
    <script nonce="${nonce}">console.log("hello!");</script>
    <h1>Hello world</h1> 
    `;
}

app.get("/", (req, res) => {
  const nonce = crypto.randomUUID();
  res.setHeader("Content-Security-Policy", `script-src 'nonce-${nonce}'`);
  res.send(content(nonce));
});

The hashes solution

The server must send an hash for each script and style present in the page. The hash is generated from the content of each <script> and <style> tag. Example:

const hash1 = "sha256-ex2O7MWOzfczthhKm6azheryNVoERSFrPrdvxRtP8DI=";
const hash2 = "sha256-H/eahVJiG1zBXPQyXX0V6oaxkfiBdmanvfG9eZWSuEc=";

const csp = `script-src '${hash1}' '${hash2}'`;
const content = `
  <script src="./main.js" integrity="${hash2}"></script>
  <script>console.log("hello!");</script>
    <h1>Hello world</h1> 
    `;

app.get("/", (req, res) => {
  res.setHeader("Content-Security-Policy", csp);
  res.send(content);
});
nonce hashes
SSG Very limited support. Requires an adapter with an edge function, and modify all the HTML to add the nonce attribute. Static hosts can't support it. Can work out-of-box with a <meta> tag
SSR Supported. Requires an adapter. Supported. Can use an adapter to enhance CSP.
Dynamic scripts Covered natively Not covered nativily. The user must supplement their hashes.
Dynamic styles Covered natively Not covered nativily. The user must supplement their hashes.
Implementation implications Probably none in core. Implement a static adapter for adapters. Very easy to achieve Might not require any work in the adapters. Requires a lot of work in core, as it touches many parts of the framework: islands (client and server), view transitions, etc. Requires some harness for future client scripts/styles.
Testing Adapter level. Probably very brittle/limited. It might require hosted tests. Achievable, but it still requires some new testing strategy to test pure SSG.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment