
Security News
Node.js Drops Bug Bounty Rewards After Funding Dries Up
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.
secure-headers-kit
Advanced tools
Easily apply secure HTTP headers, rate limiting (memory + Redis), and protection to your Express app.
Secure, safe HTTP headers middleware for Express applications with built-in rate limiting. Protect your web applications with essential security headers and request throttling out of the box.
npm install secure-headers-kit
For Redis rate limiting:
npm install secure-headers-kit redis
const express = require("express");
const { applySecureHeaders } = require("secure-headers-kit");
const app = express();
// Apply secure headers with defaults
app.use(applySecureHeaders());
app.get("/", (req, res) => {
res.send("Hello, secure world!");
});
app.listen(3000);
The middleware applies the following security headers by default:
| Header | Value | Purpose |
|---|---|---|
Content-Security-Policy | default-src 'self' | Prevents XSS attacks by controlling resource loading |
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | Enforces HTTPS connections |
X-Content-Type-Options | nosniff | Prevents MIME type sniffing |
X-Frame-Options | DENY | Prevents clickjacking attacks |
Referrer-Policy | no-referrer | Controls referrer information sharing |
Permissions-Policy | camera=(), microphone=(), geolocation=() | Restricts browser features |
// Use all default headers
app.use(applySecureHeaders());
// Override or add custom headers
app.use(
applySecureHeaders({
overrides: {
"Content-Security-Policy": "default-src 'self' 'unsafe-inline'",
"X-Custom-Header": "custom-value",
},
})
);
// Enable logging to see applied headers and rate limit events
app.use(
applySecureHeaders({
logging: true,
})
);
// Prevent accidental override of critical security headers
app.use(
applySecureHeaders({
strict: true,
overrides: {
"Content-Security-Policy": "malicious-policy", // This will be ignored
"X-Custom-Header": "safe-value", // This will be applied
},
})
);
// Basic memory-based rate limiting (60 requests per minute)
app.use(
applySecureHeaders({
rateLimit: {
windowMs: 60 * 1000, // 1 minute
maxRequests: 60,
message: "Too many requests, please try again later.",
},
})
);
const redis = require("redis");
const client = redis.createClient();
app.use(
applySecureHeaders({
rateLimit: {
type: "redis",
redisClient: client,
windowMs: 60 * 1000, // 1 minute
maxRequests: 100,
keyPrefix: "api:ratelimit:",
message: "Rate limit exceeded",
},
})
);
app.use(
applySecureHeaders({
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
maxRequests: 100,
onLimitExceeded: (req, res) => {
res.status(429).json({
error: "Rate limit exceeded",
retryAfter: "15 minutes",
timestamp: new Date().toISOString(),
});
},
},
})
);
applySecureHeaders(options?)Creates Express middleware that applies secure HTTP headers and optional rate limiting.
options (Object, optional)
overrides (Object, optional) - Custom headers to override or addstrict (boolean, optional, default: false) - Prevent overriding critical headerslogging (boolean, optional, default: false) - Enable console loggingrateLimit (Object, optional) - Rate limiting configurationwindowMs (number, default: 60000) - Time window in millisecondsmaxRequests (number, default: 60) - Maximum requests per windowmessage (string, default: "Too many requests. Please try again later.") - Error messagetype (string, default: "memory") - Storage type: "memory" or "redis"keyPrefix (string, default: "shk:") - Redis key prefixredisClient (Object, required for Redis) - Redis client instanceonLimitExceeded (Function, optional) - Custom handler for rate limit exceededExpress middleware function (req, res, next) => void
const express = require("express");
const redis = require("redis");
const { applySecureHeaders } = require("secure-headers-kit");
const app = express();
const redisClient = redis.createClient({
host: process.env.REDIS_HOST || "localhost",
port: process.env.REDIS_PORT || 6379,
});
app.use(
applySecureHeaders({
strict: true,
logging: process.env.NODE_ENV === "development",
overrides: {
"Content-Security-Policy": "default-src 'none'; frame-ancestors 'none';",
"X-API-Version": "1.0.0",
},
rateLimit: {
type: "redis",
redisClient,
windowMs: 15 * 60 * 1000, // 15 minutes
maxRequests: 1000,
keyPrefix: "api:v1:",
onLimitExceeded: (req, res) => {
res.status(429).json({
error: "API rate limit exceeded",
limit: 1000,
window: "15 minutes",
retryAfter: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
});
},
},
})
);
// Global rate limiting
app.use(
applySecureHeaders({
rateLimit: {
windowMs: 60 * 1000,
maxRequests: 60,
},
})
);
// Stricter rate limiting for auth endpoints
app.use(
"/auth",
applySecureHeaders({
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
maxRequests: 5, // Only 5 auth attempts per 15 minutes
message: "Too many authentication attempts",
},
})
);
app.use(
applySecureHeaders({
overrides: {
"Content-Security-Policy": [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com",
"img-src 'self' data: https:",
].join("; "),
},
})
);
const isDevelopment = process.env.NODE_ENV === "development";
app.use(
applySecureHeaders({
logging: isDevelopment,
overrides: {
"Content-Security-Policy": isDevelopment
? "default-src 'self' 'unsafe-inline' 'unsafe-eval'"
: "default-src 'self'",
},
rateLimit: isDevelopment
? undefined
: {
windowMs: 60 * 1000,
maxRequests: 100,
},
})
);
The middleware detects client IP addresses in the following order:
X-Forwarded-For header (first IP)req.ipreq.connection.remoteAddressDENY prevents all framing. Use SAMEORIGIN if you need to embed your pages.The following headers are considered critical and cannot be overridden in strict mode:
Content-Security-PolicyStrict-Transport-SecurityX-Content-Type-OptionsX-Frame-OptionsReferrer-PolicyPermissions-PolicyRate limiting not working:
req.ip is properly populated (you might need app.set('trust proxy', true))Redis connection errors:
Headers not applied:
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.
See CHANGELOG.md for version history and updates.
FAQs
Easily apply secure HTTP headers, rate limiting (memory + Redis), and protection to your Express app.
We found that secure-headers-kit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.