Fix CSP Nonce for Inline Scripts and Styles
In this tutorial, you'll learn about Fix CSP Nonce for Inline Scripts and Styles. We cover key concepts, practical examples, and best practices.
Inline scripts are blocked by Content Security Policy unless you use 'unsafe-inline', a hash, or a nonce. Using 'unsafe-inline' defeats CSP's XSS protection. Nonces provide a secure way to allow specific inline scripts and styles by attaching a cryptographically random token that changes on every request.
Wrong
No nonce is applied to inline scripts, or 'unsafe-inline' is used as a shortcut.
Content-Security-Policy: script-src 'self' 'unsafe-inline'
<script>
initApp();
</script>
<script>
const apiKey = 'abc123';
loadDashboard(apiKey);
</script>
The page works, but any injected script tag also executes because 'unsafe-inline' allows all inline scripts.
Right
Generate a unique nonce per request and apply it to both the CSP header and the HTML.
Server-side (Node.js with Express):
const helmet = require('helmet');
const crypto = require('crypto');
app.use((req, res, next) => {
res.locals.nonce = crypto.randomBytes(16).toString('base64');
next();
});
app.use(helmet.contentSecurityPolicy({
directives: {
scriptSrc: [
"'self'",
(req, res) => `'nonce-${res.locals.nonce}'`,
],
},
}));
<script nonce="abc123def456ghi789">
initApp();
</script>
<script nonce="abc123def456ghi789">
const apiKey = 'abc123';
loadDashboard(apiKey);
</script>
The browser only executes inline scripts whose nonce attribute matches the 'nonce-...' value in the CSP header:
Content-Security-Policy: script-src 'self' 'nonce-abc123def456ghi789'
Any injected script without the correct nonce is blocked:
<!-- This injected script is blocked -->
<script>
stealData();
</script>
Prevention
- Generate a fresh cryptographically random nonce for every HTTP request using
crypto.randomBytes(). - Do not reuse nonces across requests or sessions. Each page load must have a unique nonce.
- Apply the nonce attribute to every
<script>and<style>tag that runs inline code. - Use template injection to pass the nonce from the server to the HTML template.
- When using frameworks like React, use the framework's nonce integration (e.g.,
nonceprop on script tags). - Avoid
'unsafe-inline'when nonces are configured. Browsers ignore'unsafe-inline'when a nonce is present in modern browsers.
DodaTech Tools
Doda Browser's CSP inspector shows which nonces are valid on the page and highlights inline scripts that lack a matching nonce. DodaZIP's template scanner validates that every inline script tag has a nonce attribute. Durga Antivirus Pro uses per-request nonces across all its web-based management interfaces to prevent stored XSS.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro