Content Security Policy (CSP) is a powerful security mechanism that helps prevent various web vulnerabilities, including Cross-Site Scripting (XSS), clickjacking, and code injection attacks. This chapter explains CSP implementation in Express.js, from understanding its purpose to advanced configuration techniques.
CSP is a security standard that allows you to specify which sources of content (scripts, styles, images, etc.) are allowed to load on a webpage. It acts as a whitelist for content, blocking unauthorized resources.
A CSP is delivered via an HTTP header (Content-Security-Policy
) or a <meta>
tag in HTML. The browser enforces the policy, blocking any content that doesn’t match the defined rules.
default-src
: Specifies the default content source for all types.script-src
: Controls the allowed sources for JavaScript.style-src
: Specifies allowed sources for CSS.img-src
: Restricts image sources.connect-src
: Defines permitted sources for AJAX or WebSocket connections.
Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com;
Helmet.js is a middleware package for securing Express apps. It includes built-in support for CSP.
npm install helmet
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"], // Allow only content from the same origin
scriptSrc: ["'self'", "https://trusted-scripts.com"], // Allow inline and trusted scripts
styleSrc: ["'self'", "'unsafe-inline'"], // Allow inline styles
imgSrc: ["'self'", "data:"], // Allow same-origin and base64-encoded images
connectSrc: ["'self'", "https://api.example.com"], // Allow AJAX/WebSocket connections
},
})
);
app.get('/', (req, res) => {
res.send('Hello, World!
');
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
defaultSrc
: Sets the default source for all content types.scriptSrc
: Allows JavaScript from the current domain and specific external domains.styleSrc
: Permits inline styles ('unsafe-inline'
).imgSrc
: Limits images to same-origin or base64-encoded data.You can also manually set the Content-Security-Policy
header.
const express = require('express');
const app = express();
// Custom CSP middleware
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' https://trusted-cdn.com; img-src 'self' data:;"
);
next();
});
app.get('/', (req, res) => {
res.send('Custom CSP Implementation
');
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
When a violation occurs, the browser blocks the resource and logs a message to the console. You can monitor violations using CSP reports.
CSP can report violations to a specified endpoint using the report-uri
or report-to
directive.
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
reportUri: '/csp-violations', // Deprecated
reportTo: 'csp-endpoint', // New standard
},
reportOnly: true, // Enable report-only mode for testing
})
);
// Endpoint to log CSP violations
app.post('/csp-violations', express.json(), (req, res) => {
console.log('CSP Violation:', req.body);
res.sendStatus(204);
});
reportUri
: Specifies a URL where violation reports are sent (deprecated).reportTo
: Modern way to define reporting groups.reportOnly
: Allows testing the policy without blocking contentNonces are unique tokens generated for each request, allowing specific inline scripts to execute.
app.use((req, res, next) => {
res.locals.nonce = 'unique-nonce-value'; // Generate a secure random value in production
res.setHeader(
'Content-Security-Policy',
`script-src 'self' 'nonce-${res.locals.nonce}'`
);
next();
});
app.get('/', (req, res) => {
res.send(` `);
});
nonce
value execute, mitigating inline script vulnerabilities.For large applications with different pages requiring distinct policies, dynamically generate CSP headers based on routes.
app.use((req, res, next) => {
const cspDirectives = req.path === '/admin'
? "default-src 'self'; script-src 'self' https://admin-scripts.com;"
: "default-src 'self'; script-src 'self';";
res.setHeader('Content-Security-Policy', cspDirectives);
next();
});
'unsafe-inline'
and 'unsafe-eval'
: Avoid them to strengthen security.Implementing a Content Security Policy (CSP) in Express.js is a critical step toward building secure web applications. By specifying trusted sources for scripts, styles, and other resources, CSP protects against common vulnerabilities like XSS and data injection attacks.Through the techniques and examples in this chapter, you’ve learned to implement CSP using Helmet.js, custom middleware, and advanced configurations. Adopting these practices ensures your applications are robust, resilient, and secure. Happy coding !❤️