Content Security Policy (CSP) is a browser mechanism that allows application developers to define which resources may be loaded and executed in the context of a page. With CSP you can significantly reduce the risk of cross‑site scripting (XSS) attacks and other unwanted behaviors, such as injection of unauthorized JavaScript code. In environments based on Next.js and React, where components are rendered dynamically, implementing CSP requires thoughtful configuration so as not to disrupt application functionality.
Threat model – why CSP is needed in React/Next.js applications
Modern front‑end applications often load scripts from many sources: CDNs, your own server, and also dynamically generated inline scripts (e.g., embedded in HTML templates). Attackers can exploit input‑sanitization flaws to inject their own JavaScript, leading to token theft, session hijacking, or execution of unauthorized operations. CSP acts as a defensive layer, blocking unauthorized sources and enforcing the use of safe resource‑loading methods.
How CSP works – core directives and their meaning
The CSP policy is defined in the HTTP header Content‑Security‑Policy or in a <meta> tag. The most important directives are:
default-src– default source for all resource types when no other directive is specified.script-src– controls where JavaScript scripts may originate.style-src– defines allowed sources for CSS stylesheets.img-src– governs the origin of images.connect-src– defines which endpoints the application may connect to (e.g., APIs, WebSocket).
In practice the most critical directive is script-src, because it directly protects against XSS. It is recommended to use hashes ('sha256-…') or nonces ('nonce‑…') for inline scripts instead of relying on 'unsafe-inline', which disables protection.
Sample CSP policy for Next.js
Below is a minimal yet effective CSP policy that can be added in next.config.js using middleware or in the getServerSideProps function:
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'sha256-abc123' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://api.example.com; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'"
}
]
}
];
}
};
This policy allows scripts only from your own host and a trusted CDN, and inline scripts must be protected with a hash. For styles, 'unsafe-inline' is permitted only in exceptional cases, which is a compromise when using CSS‑in‑JS libraries.
Code snippets: vulnerable vs. fixed
Consider a simple React component that inserts content fetched from an API without sanitization:
function UnsafeComponent({html}) {
return ;
}
This approach is vulnerable to XSS because any HTML code could be executed. The corrected version uses a sanitization library and also restricts CSP to trusted sources:
import DOMPurify from 'dompurify';
function SafeComponent({html}) {
const cleanHtml = DOMPurify.sanitize(html);
return ;
}
Combining application‑side sanitization with a strict CSP dramatically raises the security level.
“CSP is not a magic shield – it is a component of the defense layer that must work together with secure code.”
CSP implementation checklist for Next.js and React
- Identify all script, style, image, and connection sources used in the project.
- Determine which inline scripts are essential; replace them with hashes or nonces.
- Configure the CSP header in
next.config.jsor in the reverse‑proxy server (NGINX, Vercel). - Enable CSP reporting (the
report-uriorreport-todirective) and monitor the logs. - Test the policy in report‑only mode (
Content-Security-Policy-Report-Only) before switching to enforcing mode. - Use browser developer tools to analyze CSP violations and fine‑tune the policy.
Common mistakes and trade‑offs when implementing CSP
Typical pitfalls include:
- Using
'unsafe-inline'or'unsafe-eval'– completely disables XSS protection. - Outdated hashes – after code changes the hash must be updated, otherwise the policy blocks legitimate code.
- Overly restrictive
default-srcwithout proper matching of sub‑directives – can cause the application to stop loading essential resources such as fonts or images. - No reporting – without reporting enabled it’s hard to detect which resources are blocked and why.
The solution is an iterative approach: first run the policy in Report‑Only mode, collect data, and then switch to blocking mode after eliminating all false positives.
Debugging CSP violations in the browser and reporting
In Chrome and Firefox developer consoles you’ll see messages like Refused to load the script … because it violates the following Content Security Policy directive: "script-src …". Clicking the message opens a preview showing which source was blocked. Additionally, if report-uri is configured, the server receives a JSON payload with violation details, enabling automated analysis and policy updates.
Maintaining and updating a CSP
A CSP is not a one‑time setting – it requires regular review. Every new library, CDN, or feature (e.g., WebSocket) may necessitate adding appropriate sources to directives. A good practice is to integrate e2e tests that verify the application works with CSP enabled, and to monitor reports in a SIEM system or a dedicated endpoint.
In summary, implementing Content Security Policy in Next.js and React projects is a process that combines thorough asset inventory, proper header configuration, and continuous monitoring. This allows engineering teams to significantly reduce XSS risk while preserving full application functionality. If you need assistance with a security audit, CSP configuration, or reporting integration, contact us at Coderia.it – together we’ll build a solid protective shield for your code.



