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 🙏

© 2026 – Pkg Stats / Ryan Hefner

hodor-guard

v0.2.0

Published

Security middleware for Node.js — rate limiting, honeypot, risk scoring

Readme


What is HodorGuard?

HodorGuard is a plug-and-play security middleware for Express APIs. It silently monitors every incoming request, builds a risk score per IP, and automatically blocks suspicious behavior, with zero impact on legitimate users.

It is designed to run on limited VPS environments with low memory and CPU usage, using Redis as its only dependency.


Features

  • Rate limiting — configurable request limit per IP within a time window
  • Honeypot routes — fake endpoints that penalize any IP that accesses them
  • Risk scoring — every IP gets a dynamic score based on behavior
  • Auto blocking — IPs that exceed the risk threshold are blocked via Redis TTL
  • Scanner detection — detects IPs accessing too many different routes
  • Brute force detection — detects high-volume burst patterns
  • Flood detection — detects sustained high request rates
  • Request logging — lightweight 24h logs stored in Redis
  • Monitoring endpoints — built-in HTTP endpoints to inspect runtime data
  • Dual package — supports both CommonJS and ES Modules consumers

Requirements

  • Node.js >= 18.0.0
  • Redis server reachable from your application
  • Express >= 4.0.0 (Express 5 fully supported)

Tested compatibility

| Setup | Status | | ---------------------------------- | ------------------------------------------------- | | Express 4 + CommonJS | ✅ tested | | Express 5 + ESM (tsx, ts-node ESM) | ✅ tested | | NestJS | ⚠️ not yet tested | | Fastify | ❌ not supported (different middleware system) | | Koa | ❌ not supported (different middleware signature) |


Installation

npm install hodor-guard

Redis is required. HodorGuard uses it for all state management, counters, scores, blocks and logs.


Quick start (Express + ESM)

import express from 'express';
import { hodorGuard } from 'hodor-guard';
import { statsRouter } from 'hodor-guard/router';

const app = express();

app.use(
  hodorGuard({
    rateLimit: true,
    honeypot: true,
    autoBlock: true,
  }),
);

// optional mount monitoring endpoints
app.use('/hodor', statsRouter);

app.listen(3000);

Quick start (Express + CommonJS)

const express = require('express');
const { hodorGuard } = require('hodor-guard');
const { statsRouter } = require('hodor-guard/router');

const app = express();

app.use(
  hodorGuard({
    rateLimit: true,
    honeypot: true,
    autoBlock: true,
  }),
);

app.use('/hodor', statsRouter);

app.listen(3000);

Configuration

All options are optional. HodorGuard uses sensible defaults out of the box.

| Option | Type | Default | Description | | -------------------- | ---------- | --------- | ----------------------------------------- | | rateLimit | boolean | true | Enable rate limiting | | honeypot | boolean | true | Enable honeypot routes | | autoBlock | boolean | true | Enable automatic IP blocking | | rateLimitMax | number | 100 | Max requests per window per IP | | rateLimitWindowMs | number | 60000 | Time window in milliseconds | | riskScoreThreshold | number | 70 | Score at which an IP gets blocked (0–100) | | blockTtlSeconds | number | 900 | How long a blocked IP stays blocked | | scannerThreshold | number | 10 | Unique routes before flagging as scanner | | honeypotRoutes | string[] | see below | Routes that trigger honeypot penalty | | logRequests | boolean | true | Store request logs in Redis |

Default honeypot routes

/admin  /admin/login  /wp-admin  /wp-login.php
/phpmyadmin  /config  /.env  /backup  /shell  /console

Configuration best practices

⚠️ Honeypot routes must not collide with real routes

Honeypot routes are designed to catch attackers, any IP that accesses them gets a heavy penalty. If you have a real route that matches a default honeypot path, that route will trap your legitimate users.

Example: if your application has a real /admin panel, the default honeypot list will block your administrators after a few legitimate accesses.

Two safe patterns:

1. Use obscure paths for sensitive routes (recommended)

// instead of /admin, use a non-obvious path
app.get('/secret-panel-x9k2', adminHandler);

Default honeypots stay enabled, anyone hitting /admin is an attacker.

2. Override the honeypot list to remove conflicting paths

app.use(
  hodorGuard({
    honeypotRoutes: ['/wp-admin', '/.env', '/phpmyadmin', '/shell'],
    // /admin removed your app uses it legitimately
  }),
);

Behind a reverse proxy

If your app runs behind a reverse proxy (Nginx, Caddy, Cloudflare), enable Express trust proxy so HodorGuard can read the real client IP from x-forwarded-for:

app.set('trust proxy', 1);

Risk scoring

Each suspicious behavior adds points to the IP's risk score. When the score reaches the threshold, the IP is blocked.

| Behavior | Penalty | | ----------------------- | ------- | | Honeypot route accessed | +40 | | Brute force detected | +25 | | Rate limit exceeded | +20 | | Scanner detected | +15 | | Flood detected | +10 |


Monitoring endpoints

Mount statsRouter to expose runtime data:

app.use('/hodor', statsRouter);

| Endpoint | Description | | --------------------------- | --------------------------------- | | GET /hodor/stats | Global request and block counters | | GET /hodor/blocked | All currently blocked IPs | | GET /hodor/top-attackers | Blocked IPs sorted by risk score | | GET /hodor/logs/:ip | Request logs for a specific IP | | GET /hodor/ip/:ip | Full risk data for a specific IP | | DELETE /hodor/blocked/:ip | Manually unblock an IP |

⚠️ The monitoring endpoints have no authentication built in. Mount them behind your own auth middleware in production.


Environment variables

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=

Running the example

Clone the repo and start the demo server:

git clone https://github.com/pecinallib/hodor-guard.git
cd hodor-guard
npm install
cp .env.example .env
npm run example

In a second terminal, run the attack simulator:

npm run simulator

Watch HodorGuard detect and block brute force, scanner, honeypot and flood attacks in real time.


Running tests

npm test
npm run test:coverage

IP risk data structure

{
  "ip": "192.168.0.1",
  "riskScore": 87,
  "flags": ["honeypot_access", "brute_force"],
  "blocked": true,
  "firstSeen": 1713000000000,
  "lastSeen": 1713000120000,
  "requestCount": 342
}

Limitations

  • IP spoofing — relies on x-forwarded-for header. Configure your reverse proxy to overwrite this header to prevent client-side spoofing.
  • Distributed attacks — botnets using many IPs each making few requests will not be detected on a per-IP basis.
  • Redis dependency — if Redis is unavailable, HodorGuard fails open (requests pass through). This is intentional to never block legitimate traffic on internal errors, but means your protection is offline if Redis goes down.
  • Shared IPs — corporate proxies or CDNs may share the same IP across many users. Tune rateLimitMax and riskScoreThreshold accordingly.
  • No persistence after Redis restart — without Redis persistence configured, scores and blocks are lost when Redis restarts.

License

MIT © Matheus Bastos Pecinalli