CSP Basics
Content Security Policy
What is CSP?
Content Security Policy restricts which resources can be loaded and executed.
Basic Configuration
// Simple CSP
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'"
);
next();
});
// Multiple directives
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' https://trusted.com; style-src 'self' 'unsafe-inline'"
);
next();
});
Common Directives
| Directive | Controls |
|---|---|
| default-src | Default for all resource types |
| script-src | JavaScript files |
| style-src | CSS files |
| img-src | Images |
| font-src | Fonts |
| connect-src | AJAX, WebSocket |
| frame-src | Iframes |
| object-src | Plugins |
| media-src | Audio/Video |
Source Values
| Value | Description |
|---|---|
| 'self' | Same origin |
| 'none' | Block all |
| 'unsafe-inline' | Allow inline |
| 'unsafe-eval' | Allow eval() |
| https: | HTTPS only |
| data: | data: URIs |
| blob: | blob: URIs |
| domain.com | Specific domain |
Example Policies
// Strict policy
"default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self';"
// Relaxed policy
"default-src 'self' https:; script-src 'self' https://trusted.com;"
// Inline styles only
"default-src 'self'; style-src 'self' 'unsafe-inline';"
CSP Directives
CSP Directives
Script Sources
// Only same origin
script-src 'self'
// Specific CDN
script-src 'self' https://cdn.jsdelivr.net
// No inline scripts
script-src 'self'
// Allow specific inline
script-src 'self' 'nonce-abc123'
// Allow specific hash
script-src 'self' 'sha256-abc123...'
Style Sources
// Only external styles
style-src 'self'
// Allow inline styles
style-src 'self' 'unsafe-inline'
// Specific CDN
style-src 'self' https://fonts.googleapis.com
Image Sources
// Only same origin
img-src 'self'
// Allow data URIs
img-src 'self' data:
// Allow any HTTPS
img-src 'self' https:
// Specific domains
img-src 'self' https://images.example.com https://cdn.example.com
},
{
"id": "ch3",
"title": "Advanced CSP",
"content": "## Advanced CSP
Nonces and Hashes
// Generate nonce per request
const nonce = crypto.randomBytes(16).toString('base64');
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
`script-src 'self' 'nonce-${nonce}'; style-src 'self' 'nonce-${nonce}'`
);
res.locals.nonce = nonce;
next();
});
// In template
<script nonce="{nonce}">
// Inline script with nonce
</script>
// Hash-based
const hash = crypto
.createHash('sha256')
.update('console.log("hello")')
.digest('base64');
script-src 'self' 'sha256-${hash}'
Reporting
// CSP Report-Only header
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy-Report-Only',
"default-src 'self'; report-uri /csp-report"
);
next();
});
// Report endpoint
app.post('/csp-report', (req, res) => {
const report = req.body;
console.log('CSP Violation:', report);
res.status(204).end();
});
// Report-To header (newer)
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; report-to csp-endpoint"
);
res.setHeader(
'Report-To',
JSON.stringify({
group: 'csp-endpoint',
endpoints: [{ url: '/csp-report' }],
max_age: 10886400,
})
);
next();
});
React CSP Implementation
// server.js
import { randomBytes } from 'crypto';
function generateNonce() {
return randomBytes(16).toString('base64');
}
app.use((req, res, next) => {
const nonce = generateNonce();
res.locals.nonce = nonce;
const csp = [
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}'`,
`style-src 'self' 'nonce-${nonce}'`,
"img-src 'self' data: https:",
"font-src 'self' https://fonts.gstatic.com",
"connect-src 'self' https://api.example.com",
"frame-ancestors 'none'",
].join('; ');
res.setHeader('Content-Security-Policy', csp);
next();
});
// React component
function App({ nonce }) {
return (
<html>
<head>
<script nonce={nonce} src="/bundle.js"></script>
<style nonce={nonce}>{css}</style>
</head>
<body>
<div id="root"></div>
</body>
</html>
);
}
Common CSP Mistakes
- Using 'unsafe-inline' (weakens CSP)
- Using 'unsafe-eval' (allows eval())
- Overly permissive policies (https: or *)
- Not testing in report-only mode first
- Missing directives (default-src fallback)
- Not handling nonce properly
Testing CSP
// Test CSP headers
describe('CSP', () => {
it('should set CSP header', async () => {
const response = await request(app).get('/');
expect(response.headers['content-security-policy']).toBeDefined();
});
it('should not allow unsafe-inline', async () => {
const response = await request(app).get('/');
expect(response.headers['content-security-policy'])
.not.toContain('unsafe-inline');
});
});
Practice Problems
Create a reusable React component implementing Content Security Policy (CSP). Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Content Security Policy (CSP) using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Content Security Policy (CSP) for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What is CSP?
2. What does 'unsafe-inline' allow?
3. What is the primary purpose of Content Security Policy (CSP)?
4. What is a common mistake when implementing Content Security Policy (CSP)?
Flashcards
Question
What is CSP?
Click to reveal answer
Answer
Content Security Policy - an HTTP header that restricts resource loading and execution.
Question
What is the default-src directive?
Click to reveal answer
Answer
Fallback for all resource types when specific directive is not set.
Question
Why avoid unsafe-inline?
Click to reveal answer
Answer
It allows inline scripts/styles, making XSS attacks easier.
Question
What is Report-Only mode?
Click to reveal answer
Answer
Reports CSP violations without blocking resources, useful for testing.
Question
What is Content Security Policy (CSP)?
Click to reveal answer
Answer
Content Security Policy (CSP) is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.CSP restricts which resources can be loaded
- 2.Use nonces instead of unsafe-inline
- 3.Start with Report-Only for testing
- 4.Be specific with allowed domains
- 5.CSP is a critical defense against XSS
Interview Tips
- •Explain CSP directives and source values
- •Discuss nonces vs hashes for inline scripts
- •Know common CSP configuration mistakes
Cheat Sheet
CSP Cheat Sheet
Directives
- default-src: Fallback for all
- script-src: JavaScript
- style-src: CSS
- img-src: Images
- connect-src: AJAX/WebSocket
Source Values
- 'self': Same origin
- 'none': Block all
- 'unsafe-inline': Inline scripts (avoid)
- 'nonce-abc': Allow specific inline
- https: HTTPS only
Best Practices
- Start with Report-Only
- Use nonces for inline
- Don't use unsafe-inline/eval
- Be specific with domains
- Set frame-ancestors 'none'
Header Example
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc';