How to Use Content Security Policy in Express for Secure Apps
To use
Content Security Policy (CSP) in Express, install the helmet middleware and configure its contentSecurityPolicy option with your desired rules. Then add it as middleware in your Express app to set CSP headers that control which resources can load.Syntax
The basic syntax involves importing helmet and using its contentSecurityPolicy middleware in your Express app. You provide a directives object that defines allowed sources for scripts, styles, images, etc.
- helmet(): Main security middleware that can enable many protections.
- contentSecurityPolicy({ directives }): Middleware to set CSP headers with rules.
- directives: Object specifying allowed sources like
'self', URLs, or'none'.
javascript
import express from 'express'; import helmet from 'helmet'; const app = express(); app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", 'trusted.com'], styleSrc: ["'self'", 'fonts.googleapis.com'], imgSrc: ["'self'", 'images.com'], connectSrc: ["'self'"], fontSrc: ["'self'", 'fonts.gstatic.com'], objectSrc: ["'none'"], upgradeInsecureRequests: [], }, }) ); app.get('/', (req, res) => { res.send('Hello, CSP!'); }); app.listen(3000);
Example
This example shows a simple Express server using helmet to set a Content Security Policy that only allows scripts and styles from the same origin and trusted domains. It protects your app by blocking unauthorized resource loading.
javascript
import express from 'express'; import helmet from 'helmet'; const app = express(); app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", 'cdn.example.com'], styleSrc: ["'self'", 'cdn.example.com'], imgSrc: ["'self'"], objectSrc: ["'none'"], upgradeInsecureRequests: [], }, }) ); app.get('/', (req, res) => { res.send('<h1>Content Security Policy is active!</h1>'); }); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });
Output
Server running on http://localhost:3000
Common Pitfalls
Common mistakes when using CSP in Express include:
- Not allowing needed sources, causing resources like scripts or styles to be blocked unexpectedly.
- Forgetting to include
'self'in directives, which blocks your own domain's resources. - Using overly permissive rules like
*orunsafe-inlinewhich weaken security. - Not testing CSP headers in different browsers or environments.
Always tailor directives to your app's needs and test carefully.
javascript
/* Wrong: Allows unsafe inline scripts, weakening security */ app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'unsafe-inline'", "'self'"] } }) ); /* Right: Avoids unsafe-inline, uses hashes or nonces if inline scripts needed */ app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'"] } }) );
Quick Reference
Here is a quick summary of common CSP directives used with helmet.contentSecurityPolicy:
| Directive | Purpose | Example Values |
|---|---|---|
| defaultSrc | Fallback for all resource types | 'self', 'none', https://example.com |
| scriptSrc | Allowed script sources | 'self', 'unsafe-inline', cdn.example.com |
| styleSrc | Allowed style sources | 'self', 'unsafe-inline', fonts.googleapis.com |
| imgSrc | Allowed image sources | 'self', data:, images.com |
| connectSrc | Allowed AJAX, WebSocket connections | 'self', api.example.com |
| fontSrc | Allowed font sources | 'self', fonts.gstatic.com |
| objectSrc | Allowed plugin/object sources | 'none' |
| upgradeInsecureRequests | Automatically upgrade HTTP to HTTPS | Empty array [] to enable |
Key Takeaways
Use helmet's contentSecurityPolicy middleware to set CSP headers in Express.
Define clear directives to specify trusted sources for scripts, styles, images, and more.
Avoid unsafe directives like 'unsafe-inline' unless absolutely necessary.
Test your CSP rules to ensure your app resources load correctly without security gaps.
Include 'self' in directives to allow your own domain's resources.