All Docs
FeaturesCalmony Sanctions MonitorUpdated March 11, 2026

Security Hardening: Nonce-Based CSP Replaces unsafe-inline and unsafe-eval

Security Hardening: Nonce-Based CSP Replaces unsafe-inline and unsafe-eval

Release: v0.1.4
Compliance framework: ISO/IEC 27001 — Control ISO-01
Affected file: next.config.ts, middleware.ts


Background

Content Security Policy (CSP) is a browser-enforced mechanism that controls which scripts, styles, and other resources a page is permitted to load and execute. A well-configured script-src directive is one of the most effective mitigations against Cross-Site Scripting (XSS) attacks.

Prior to v0.1.4, the application's CSP included two directives that significantly undermined this protection:

DirectiveRisk
'unsafe-eval'Permits eval(), new Function(), and similar runtime code evaluation. Any code path — including attacker-injected content — can execute arbitrary JavaScript.
'unsafe-inline'Permits inline <script> tags and javascript: URLs. This is the primary vector for reflected and stored XSS payloads.

With both directives present, the CSP provided no meaningful protection against script injection: a successful XSS attack would have executed without any browser-level block.


What Changed

'unsafe-eval' Removed

'unsafe-eval' is only required when application code calls eval(), new Function(), setTimeout(string), or similar constructs. No such patterns exist in this codebase, so the directive has been unconditionally removed.

'unsafe-inline' Replaced with Per-Request Nonces

Rather than permitting all inline scripts, the application now generates a cryptographically unique nonce on every HTTP request. Only <script> elements that carry the matching nonce attribute are permitted to execute.

How it works:

  1. middleware.ts generates a random nonce for each incoming request.
  2. The nonce is written into the Content-Security-Policy response header:
    Content-Security-Policy: script-src 'self' 'nonce-<random-value>'
    
  3. The nonce is passed to Next.js via the next/headers API, using Next.js 15's built-in nonce support.
  4. Next.js automatically stamps the nonce onto all framework-managed <script> tags in the rendered HTML.
  5. Any injected script that does not carry the correct nonce — including attacker-controlled content — is blocked by the browser before execution.

Because the nonce changes on every request, an attacker cannot pre-compute or reuse a valid nonce even if they can observe a previous response.


Compliance Alignment

This change directly addresses ISO/IEC 27001 Control ISO-01 requirements for application-layer security controls. A CSP containing 'unsafe-inline' or 'unsafe-eval' is considered a misconfiguration under this control framework, as it negates the stated security benefit of the header.


Impact on Developers

  • No eval() usage: If future code requires dynamic evaluation, raise a security review before re-introducing 'unsafe-eval'.
  • Inline scripts: Do not add raw <script> blocks to page markup. Use Next.js <Script> components or module imports — these will receive the nonce automatically.
  • Third-party scripts: Any third-party <script> tag added to the application must be loaded via the Next.js <Script> component so the nonce is applied. Inline event handlers (onclick="...") are not permitted under the new policy.
  • Testing: Browser developer tools will display CSP violations in the console. A blocked script that should be permitted indicates a missing nonce — fix the injection mechanism rather than relaxing the policy.