npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

secure-headers-kit

v1.2.0

Published

Easily apply secure HTTP headers, rate limiting (memory + Redis), and protection to your Express app.

Readme

secure-headers-kit

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.

Features

  • 🛡️ Secure by default - Applies essential security headers automatically
  • 🚦 Built-in rate limiting - Memory and Redis-based request throttling
  • Zero dependencies - Lightweight and fast (Redis optional)
  • 🔧 Customizable - Override or add custom headers as needed
  • 🔒 Strict mode - Prevent accidental override of critical security headers
  • 📊 Optional logging - Debug and monitor header application and rate limits
  • 📦 Easy integration - Simple Express middleware

Installation

npm install secure-headers-kit

For Redis rate limiting:

npm install secure-headers-kit redis

Quick Start

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);

Default Headers

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 |

Configuration

Basic Usage

// Use all default headers
app.use(applySecureHeaders());

Custom Headers

// Override or add custom headers
app.use(
  applySecureHeaders({
    overrides: {
      "Content-Security-Policy": "default-src 'self' 'unsafe-inline'",
      "X-Custom-Header": "custom-value",
    },
  })
);

Enable Logging

// Enable logging to see applied headers and rate limit events
app.use(
  applySecureHeaders({
    logging: true,
  })
);

Strict Mode

// 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
    },
  })
);

Rate Limiting

Memory-based Rate Limiting

// 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.",
    },
  })
);

Redis-based Rate Limiting

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",
    },
  })
);

Custom Rate Limit Handler

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(),
        });
      },
    },
  })
);

API Reference

applySecureHeaders(options?)

Creates Express middleware that applies secure HTTP headers and optional rate limiting.

Parameters

  • options (Object, optional)
    • overrides (Object, optional) - Custom headers to override or add
    • strict (boolean, optional, default: false) - Prevent overriding critical headers
    • logging (boolean, optional, default: false) - Enable console logging
    • rateLimit (Object, optional) - Rate limiting configuration

Rate Limit Options

  • windowMs (number, default: 60000) - Time window in milliseconds
  • maxRequests (number, default: 60) - Maximum requests per window
  • message (string, default: "Too many requests. Please try again later.") - Error message
  • type (string, default: "memory") - Storage type: "memory" or "redis"
  • keyPrefix (string, default: "shk:") - Redis key prefix
  • redisClient (Object, required for Redis) - Redis client instance
  • onLimitExceeded (Function, optional) - Custom handler for rate limit exceeded

Returns

Express middleware function (req, res, next) => void

Examples

Production API with Redis Rate Limiting

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(),
        });
      },
    },
  })
);

Different Rate Limits for Different Routes

// 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",
    },
  })
);

Content Security Policy Configuration

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("; "),
    },
  })
);

Development vs Production

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,
        },
  })
);

Rate Limiting Details

Memory Storage

  • Stores rate limit data in application memory
  • Resets when application restarts
  • Suitable for single-instance applications
  • No external dependencies

Redis Storage

  • Persistent rate limiting across application restarts
  • Suitable for multi-instance/clustered applications
  • Requires Redis server
  • Automatic key expiration

IP Address Detection

The middleware detects client IP addresses in the following order:

  1. X-Forwarded-For header (first IP)
  2. req.ip
  3. req.connection.remoteAddress

Security Considerations

  • Content Security Policy: The default CSP is restrictive. Customize it for your application's needs.
  • Strict Transport Security: Only use HSTS if you're serving over HTTPS.
  • Frame Options: DENY prevents all framing. Use SAMEORIGIN if you need to embed your pages.
  • Rate Limiting: Choose appropriate limits based on your application's expected traffic.
  • Redis Security: Secure your Redis instance with authentication and network restrictions.
  • Regular Updates: Keep your security headers up to date with current best practices.

Critical Headers

The following headers are considered critical and cannot be overridden in strict mode:

  • Content-Security-Policy
  • Strict-Transport-Security
  • X-Content-Type-Options
  • X-Frame-Options
  • Referrer-Policy
  • Permissions-Policy

Performance Considerations

  • Memory rate limiting has O(1) lookup time
  • Redis rate limiting adds network latency but provides persistence
  • Consider using Redis for production applications with multiple instances
  • Rate limit cleanup for memory storage happens automatically during requests

Troubleshooting

Common Issues

Rate limiting not working:

  • Ensure the middleware is applied before your routes
  • Check if req.ip is properly populated (you might need app.set('trust proxy', true))

Redis connection errors:

  • Verify Redis server is running and accessible
  • Check Redis client configuration and credentials

Headers not applied:

  • Ensure middleware is added before routes
  • Check for conflicting middleware that might override headers

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Related Resources

Changelog

See CHANGELOG.md for version history and updates.