When building modern web applications, security is not optional. One of the most important protections you can add is a Content Security Policy (CSP).
But here’s the catch:
👉 CSP often blocks inline scripts and styles — which can break your app.
So how do you keep your app secure without disabling useful features?
That’s where CSP nonce comes in - it allows you to safely execute inline code without opening security holes.
In this article, we’ll explore:
- What CSP nonce is
- What problem it solves
- How to implement it
- How it works automatically in Nuxt with
nuxt-security - Best practices and common pitfalls
Let’s dive in.
🤔 What Is CSP Nonce?
A nonce (short for number used once) is a unique, random value generated for each request.
It is used in CSP to explicitly allow trusted inline scripts or styles.
Example:
<script nonce="abc123">
console.log('Secure inline script')
</script>
And in your HTTP headers:
Content-Security-Policy: script-src 'nonce-abc123'
The browser will only execute scripts that have a matching nonce.
CSP nonce is a whitelist mechanism:
- Only scripts with the correct nonce are allowed
- Everything else is blocked
- The nonce changes on every request
This makes it extremely effective against XSS (Cross-Site Scripting) attacks.
CSP nonce is commonly used for:
- SSR frameworks - Injecting initial state, Hydration scripts
- Analytics / tracking snippets - Inline scripts required by providers
- Critical inline scripts - Small scripts needed before app bootstraps
🟢 What Problem Does CSP Nonce Solve?
Without nonce, you usually face a trade-off:
❌ Allow inline scripts (unsafe)
Content-Security-Policy: script-src 'unsafe-inline'
Problem:
- Opens the door to XSS attacks
- Any injected script can run
❌ Block inline scripts completely
Content-Security-Policy: script-src 'self'
Problem:
- breaks inline event handlers
- breaks injected scripts (SSR hydration, state)
- breaks some frameworks
🟢 How to Implement CSP Nonce
The process is relatively simple but let's break it down and explain each step individually.
Step 1: Generate a nonce per request
Example (Node.js):
import crypto from 'crypto'
function generateNonce() {
return crypto.randomBytes(16).toString('base64')
}
Step 2: Add it to response headers
const nonce = generateNonce()
res.setHeader(
'Content-Security-Policy',
`script-src 'nonce-${nonce}'`
)
Step 3: Inject it into your HTML
<script nonce="{{nonce}}">
window.__INITIAL_STATE__ = {}
</script>
⚠️ Critical rule
The nonce in the header and HTML must match exactly. Otherwise, script will be blocked and app may break silently.
🟢 CSP Nonce in Nuxt (with nuxt-security)
If you’re using Nuxt, things get much easier thanks to nuxt-security module that can:
- Automatically generate nonce per request
- Inject it into CSP headers
- Attach it to scripts/styles
It makes it much easier to work with CSP nonces in Nuxt. Let's take a look at the following configuration:
export default defineNuxtConfig({
modules: ['nuxt-security'],
security: {
headers: {
contentSecurityPolicy: {
'script-src': [
"'self'",
"'nonce-{{nonce}}'"
]
}
}
}
})
What happens automatically:
- Nuxt generates a nonce per request
- Replaces
{{nonce}}in headers - Applies nonce to inline scripts
You don’t need to manually wire everything
You can read more here:
https://nuxt-security.vercel.app/
🟢 Common Mistakes
Let's take a look at the list of common mistakes to understand what to look for:
- ❌ Reusing the same nonce - Nonce must be unique per request and cryptographically random
- ❌ Forgetting to apply nonce in HTML - if you only set CSP header the scripts will still be blocked
- ❌ Mixing nonce with unsafe-inline -
script-src 'unsafe-inline' 'nonce-abc' - ❌ Caching issues - if HTML is cached nonce may not match header
🧪 Best Practices
- Generate nonce per request
- Use secure randomness (
crypto) - Never reuse nonce
- Avoid
unsafe-inline - Use frameworks/tools (like nuxt-security)
- Test CSP in report-only mode first
- Monitor browser console for CSP violations
📖 Learn more
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉
🧪 Advance skills
A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.
Check out Certificates.dev by clicking this link or by clicking the image below:
Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!
✅ Summary
CSP nonce is a powerful mechanism that allows you to safely use inline scripts while maintaining strong security.
In this article, you learned:
- What CSP nonce is and how it works
- What problem it solves (security vs flexibility)
- How to implement it step by step
- How Nuxt + nuxt-security handle it automatically
- Common mistakes and best practices
Take care!
And happy coding as always 🖥️
This article was originally published by DEV Community and written by Jakub Andrzejewski.
Read original article on DEV Community
