How do I implement content security policy (CSP) to prevent XSS attacks?

Asked 2 years ago Updated 9 hours ago 550 views

1 Answer


0

Content Security Policy (CSP) gives the browser rules about which scripts and other resources a page may load. It can limit the impact of cross-site scripting (XSS), but it does not replace safe output encoding, input handling, or fixing the underlying injection bug.

Start with a nonce-based policy

For scripts, a per-response nonce is usually a better starting point than allowing all inline scripts with 'unsafe-inline'. Generate a fresh, cryptographically random nonce for every response, put it in the CSP header, and add the same value to each script element your server intentionally renders.

const crypto = require('node:crypto');

app.use((req, res, next) => {
  // Generate a new unpredictable nonce for this response.
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.cspNonce = nonce;

  // Restrict resource loading; adjust the sources to match your application.
  res.setHeader(
    'Content-Security-Policy',
    [
      "default-src 'self'",
      `script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`,
      "style-src 'self'",
      "img-src 'self' data:",
      "font-src 'self'",
      "connect-src 'self'",
      "object-src 'none'",
      "base-uri 'self'",
      "form-action 'self'",
      "frame-ancestors 'none'"
    ].join('; ')
  );

  // Continue after setting the policy and making the nonce available to views.
  next();
});

In an EJS view, for example, an approved script can use that same nonce: <script nonce="<%= cspNonce %>" src="/js/app.js"></script>. Keep the nonce unpredictable, generate it for every response, and never let untrusted input control which script elements receive it. The policy above also blocks plugins, restricts the document base URL, and prevents the page from being framed; review each directive against your app’s actual needs.

Roll it out carefully

A strict policy can block legitimate scripts, styles, images, or API connections if their sources are missing. Start by testing a Content-Security-Policy-Report-Only header and reviewing browser violations. Then enforce the policy and keep monitoring reports as the site changes. Avoid adding 'unsafe-inline' or 'unsafe-eval' just to silence violations; prefer nonces or hashes for scripts and move inline code into approved files where practical.

CSP is defense in depth: pair it with context-aware output encoding, safe templating, and careful handling of user-provided content.

Write Your Answer