Helmet Complete Guide
이 글의 핵심
Helmet helps secure Express apps by setting various HTTP headers. It's a collection of 15 smaller middleware functions that set security-related headers.
Introduction
Helmet helps secure Express apps by setting HTTP security headers. It’s not a silver bullet, but it provides an important layer of defense against common attacks.
Why Helmet?
Without Helmet, your Express app exposes information and is vulnerable:
// Without Helmet
app.get('/', (req, res) => {
res.send('Hello');
});
// Response headers:
// X-Powered-By: Express (exposes framework)
// (missing security headers)
With Helmet:
app.use(helmet());
// Response headers now include:
// Content-Security-Policy: ...
// X-DNS-Prefetch-Control: off
// X-Frame-Options: SAMEORIGIN
// Strict-Transport-Security: ...
// X-Content-Type-Options: nosniff
// (and more!)
1. Installation
npm install helmet
2. Basic Usage
const express = require('express');
const helmet = require('helmet');
const app = express();
// Use Helmet with defaults
app.use(helmet());
app.get('/', (req, res) => {
res.send('Hello, secure world!');
});
app.listen(3000);
3. What Helmet Does
Helmet is a collection of 15 smaller middleware:
app.use(helmet());
// Equivalent to:
app.use(helmet.contentSecurityPolicy());
app.use(helmet.crossOriginEmbedderPolicy());
app.use(helmet.crossOriginOpenerPolicy());
app.use(helmet.crossOriginResourcePolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.originAgentCluster());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());
4. Content Security Policy (CSP)
CSP prevents XSS attacks by controlling which resources can be loaded:
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
imgSrc: ["'self'", "data:", "https:"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
connectSrc: ["'self'", "https://api.example.com"],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
}));
Strict CSP (Recommended)
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"],
imgSrc: ["'self'"],
fontSrc: ["'self'"],
connectSrc: ["'self'"],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
},
}));
CSP for React/Vue Apps
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"], // React inline scripts
styleSrc: ["'self'", "'unsafe-inline'"], // CSS-in-JS
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", process.env.API_URL],
},
}));
5. HTTP Strict Transport Security (HSTS)
Forces HTTPS connections:
app.use(helmet.hsts({
maxAge: 31536000, // 1 year in seconds
includeSubDomains: true,
preload: true,
}));
// Only enable in production with HTTPS
if (process.env.NODE_ENV === 'production') {
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
}));
}
6. X-Frame-Options
Prevents clickjacking:
// Deny all framing
app.use(helmet.frameguard({ action: 'deny' }));
// Allow same origin
app.use(helmet.frameguard({ action: 'sameorigin' }));
// Allow specific domain
app.use(helmet.frameguard({
action: 'allow-from',
domain: 'https://example.com'
}));
7. X-Content-Type-Options
Prevents MIME sniffing:
app.use(helmet.noSniff());
// Sets header:
// X-Content-Type-Options: nosniff
8. Referrer Policy
Controls Referer header:
app.use(helmet.referrerPolicy({
policy: 'strict-origin-when-cross-origin'
}));
// Options:
// - no-referrer
// - no-referrer-when-downgrade
// - origin
// - origin-when-cross-origin
// - same-origin
// - strict-origin
// - strict-origin-when-cross-origin (recommended)
// - unsafe-url
9. Hide Powered By
Remove X-Powered-By header:
app.use(helmet.hidePoweredBy());
// Or manually:
app.disable('x-powered-by');
// Or fake it:
app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }));
10. Custom Configuration
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
},
frameguard: {
action: 'deny',
},
referrerPolicy: {
policy: 'strict-origin-when-cross-origin',
},
}));
11. Disable Specific Middleware
app.use(helmet({
contentSecurityPolicy: false, // Disable CSP
frameguard: false, // Disable X-Frame-Options
}));
12. Production Configuration
const express = require('express');
const helmet = require('helmet');
const app = express();
// Production-ready Helmet config
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", process.env.CDN_URL],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", process.env.API_URL],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true,
},
frameguard: {
action: 'deny',
},
referrerPolicy: {
policy: 'strict-origin-when-cross-origin',
},
}));
// Additional security
app.disable('x-powered-by');
// Trust proxy (if behind reverse proxy)
app.set('trust proxy', 1);
app.listen(process.env.PORT || 3000);
13. With CORS
const helmet = require('helmet');
const cors = require('cors');
// Apply Helmet first
app.use(helmet());
// Then CORS
app.use(cors({
origin: process.env.FRONTEND_URL,
credentials: true,
}));
14. Testing Security Headers
# Check headers with curl
curl -I https://example.com
# Look for:
# Content-Security-Policy: ...
# Strict-Transport-Security: max-age=31536000; includeSubDomains
# X-Frame-Options: DENY
# X-Content-Type-Options: nosniff
# Referrer-Policy: strict-origin-when-cross-origin
Security Scanners
# Mozilla Observatory
# https://observatory.mozilla.org/
# Security Headers
# https://securityheaders.com/
# SSL Labs
# https://www.ssllabs.com/ssltest/
15. Common Issues
Issue 1: CSP Blocking Inline Scripts
// Problem: React/Vue inline scripts blocked
<script>window.__INITIAL_STATE__ = {...}</script>
// Solution 1: Use nonce
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}'`],
},
}));
// In template:
<script nonce="<%= nonce %>">...</script>
// Solution 2: Allow unsafe-inline (less secure)
app.use(helmet.contentSecurityPolicy({
directives: {
scriptSrc: ["'self'", "'unsafe-inline'"],
},
}));
Issue 2: HSTS Breaking Local Development
// Only enable HSTS in production
if (process.env.NODE_ENV === 'production') {
app.use(helmet.hsts({
maxAge: 31536000,
}));
}
Issue 3: CSP Blocking CDN Resources
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: [
"'self'",
"https://cdn.jsdelivr.net",
"https://cdnjs.cloudflare.com",
],
styleSrc: [
"'self'",
"https://fonts.googleapis.com",
],
},
}));
16. Best Practices
1. Use Helmet in All Environments
// Development
app.use(helmet({
contentSecurityPolicy: false, // Easier debugging
}));
// Production
app.use(helmet()); // Full security
2. Test Thoroughly
// Test CSP in report-only mode first
app.use(helmet.contentSecurityPolicy({
directives: { /* ... */ },
reportOnly: true, // Only report violations, don't block
}));
3. Monitor CSP Violations
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
reportUri: '/api/csp-violation-report',
},
}));
app.post('/api/csp-violation-report', (req, res) => {
console.log('CSP Violation:', req.body);
// Log to monitoring service
res.status(204).end();
});
Summary
Helmet provides essential security headers:
- 15 security middlewares in one package
- CSP prevents XSS attacks
- HSTS enforces HTTPS
- Frameguard prevents clickjacking
- Production-ready with minimal config
Key Takeaways:
- Always use Helmet in production
- Configure CSP for your specific app
- Enable HSTS only with HTTPS
- Test security headers regularly
- Monitor CSP violations
Next Steps:
- Configure CORS
- Implement Passport Auth
- Secure Express API
Resources:
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. Complete Helmet guide for Express.js security. Learn security headers, CSP, XSS protection, and hardening Node.js applic…
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- CORS Complete Guide
- Express.js Complete Guide | Fast Node.js Web Framework
- Mongoose Complete Guide | MongoDB ODM for Node.js
Keywords Covered in This Article (Related Search Terms)
This article covers Helmet, Security, Express, Node.js, HTTP Headers, Web Security.