Content-Security-Policy Headers — SEC-11
Content-Security-Policy Headers
Release: v1.0.22 · Control: SEC-11 · Category: Infrastructure Security
Overview
Calmony Pay now sets a Content-Security-Policy (CSP) HTTP response header on every response. This header instructs browsers to enforce a strict allowlist of permitted resource sources, significantly reducing the impact of cross-site scripting (XSS) attacks — including those originating from third-party dependencies.
Background
Prior to this release, next.config.ts was empty and no CSP header was present. Without a CSP, browsers apply no policy to restrict which scripts, styles, frames, or network connections a page can load. Any successful XSS injection — whether from application code or a supply-chain compromise — would execute without any browser-level barrier.
Implementation
A headers() function has been added to next.config.ts that attaches the Content-Security-Policy header to all responses:
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'nonce-{nonce}'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self'",
"frame-ancestors 'none'",
].join('; '),
},
],
},
];
},
};
export default nextConfig;
Policy Directives
| Directive | Value | Purpose |
|---|---|---|
default-src | 'self' | Restricts all resource types to same-origin by default |
script-src | 'self' 'nonce-{nonce}' | Allows same-origin scripts and nonce-validated inline scripts |
style-src | 'self' 'unsafe-inline' | Allows same-origin styles; unsafe-inline retained for framework compatibility |
img-src | 'self' data: https: | Allows same-origin images, data URIs, and any HTTPS-hosted image |
connect-src | 'self' | Restricts fetch, XHR, and WebSocket connections to same-origin |
frame-ancestors | 'none' | Prevents this application from being embedded in any frame or iframe |
Nonce Support
Inline scripts are permitted only when they carry a valid nonce. Next.js has built-in nonce support via its Middleware layer. A cryptographically random nonce is generated per-request and injected into both the CSP header and any inline <script> tags that require it.
Refer to the Next.js CSP documentation for full details on configuring nonce-based CSP with the App Router.
Security Considerations
- XSS mitigation: Even if an attacker injects a
<script>tag, the browser will refuse to execute it unless it carries a valid nonce or originates from the same origin. - Clickjacking prevention:
frame-ancestors 'none'prevents the application from being loaded inside a frame on any external domain. - Third-party script risk: Any third-party scripts (analytics, support widgets, etc.) must be explicitly added to
script-srcor served via the nonce mechanism — they will not load by default. unsafe-inlineinstyle-src: This directive is a known trade-off for compatibility with CSS-in-JS and utility frameworks. It does not affect script execution policy.
Adding External Sources
If an integration requires loading resources from a third-party domain, update the relevant directive in next.config.ts. For example, to permit Stripe.js:
"script-src 'self' 'nonce-{nonce}' https://js.stripe.com",
"connect-src 'self' https://api.stripe.com",
Always be as specific as possible — prefer exact hostnames over wildcards.