Skip to content
New: sink guards check the query your code is about to run Read more

The firewall that runs inside your app.

LightMoon inspects each request after TLS, decompression and body parsing, where attacks actually land. OWASP CRS rules, bot and anti-detect browser checks, rate limits and adaptive DDoS mitigation for more than 30 JavaScript frameworks, with no runtime dependencies.

$ npm i lightmoon@alpha
Start free
MIT licensed Node, Bun, Deno and the edge ~50 µs per page view
server.tslive decisions
import express from 'express';
import { lightmoon } from 'lightmoon/express';
import { crsRules } from 'lightmoon/crs';

const app = express();
app.use(express.json());
app.use(lightmoon({
  preset: 'balanced',
  extraRules: crsRules(),   // 218 OWASP CRS rules
}));
96.6%balanced accuracy on 1.1 million real requestsHow we measured
1.14%of legitimate requests blocked with the full OWASP CRS onMethodology and caveats
30+framework and platform adapters, from Express to Workers
0runtime dependencies. 54 KB gzipped in your bundle

Works with the frameworks and runtimes you already use.

  • Express
  • Fastify
  • Koa
  • Hono
  • Next.js
  • Nuxt
  • SvelteKit
  • Astro
  • Remix
  • React Router
  • NestJS
  • hapi
  • Elysia
  • AdonisJS
  • SolidStart
  • Qwik
  • TanStack Start
  • Bun
  • Deno
  • Cloudflare Workers
  • Vercel
  • Netlify
  • AWS Lambda
What it does

Every layer of an edge WAF, running next to your code.

Managed rules, bot management and DDoS handling usually live in a proxy. LightMoon brings them into the process, where it can see the parsed body, the logged-in account and the query your code builds.

Sink guards

A signature can only guess whether a value is an attack. At the database call, the shell command, the file path or the outbound URL, LightMoon checks whether this request's input changed the structure of what your code is about to run. Normal names, numbers and lists pass however they look.

const guard = waf.sinks(req.lightmoon);

await db.query(guard.sql(sql));
await fetch(await guard.resolvedUrl(target));
const file = guard.path('/srv/uploads', name);
New

OWASP CRS, with fewer false positives

218 rules from CRS 4.29 plus 134 of our own signatures: SQL injection, XSS, traversal, command injection, SSRF, Log4Shell and more, with anomaly scoring and four paranoia levels.

Rules in a language you know

Custom rules use the Cloudflare rules language, so expressions you already have paste straight in. Block, allow, skip, log, score or challenge, with named IP and value lists.

Invisible browser checks

A small same-origin script checks the browser during normal page views. Automation and anti-detect browsers are stopped on their next request, and real visitors never see an interstitial.

Adaptive DDoS mitigation

Learns your normal traffic and, during a surge, tightens limits for clients that haven't passed the browser check. Verified browsers are left alone.

Response data-leak protection

Masks API keys, private keys, database URLs and card numbers before a response leaves, and swaps stack traces and SQL errors for a clean error page.

API schema validation

Point it at your OpenAPI 3 document and unknown endpoints, parameters and malformed JSON bodies are refused before your handler runs.

Rate limits and adaptive bans

Sliding windows keyed by IP, header or account. Repeat offenders earn reputation points and get banned, and bans can be pushed to Cloudflare's edge.

Breached passwords

Flags passwords from known breaches at login and sign-up with a k-anonymity lookup, so the password itself never leaves your server.

Replay before you deploy

npx lightmoon-replay access.log runs your own nginx or Apache logs through your config locally and lists what each rule would have blocked.

Threat feeds and signed rule packs

Pull published IP blocklists on a schedule, and apply Ed25519-signed emergency rule packs within minutes of a new CVE, without a redeploy.

Why in-app

Use it with your CDN, not instead of it.

A network WAF absorbs floods and sees the whole internet. LightMoon sees your application. The strongest setup is both.

A proxy in front of your app

  • Absorbs volumetric DDoS before it reaches you
  • Global IP reputation and TLS fingerprints from the raw connection
  • Bypassed by anyone who finds your origin IP
  • Sees the request before your framework parses it
  • Can't key limits by account or see the query you build

LightMoon, inside your app

  • Can't be bypassed: it is the origin
  • Inspects decompressed, parsed bodies, multipart uploads and nested JSON
  • Rate limits by user, session or API key
  • Checks responses and the queries your code runs
  • Works with no CDN at all: internal apps, previews, serverless
Two minutes to protect

One line in the framework you already use.

import { lightmoon } from 'lightmoon/express';

app.use(express.json());
app.use(lightmoon({ preset: 'balanced' }));
LightMoon Cloud

One dashboard for every instance.

Add one line to connect. Your servers keep making every decision locally; the dashboard collects what they blocked and sends back the rules you write.

  • Live attack analytics. Blocks, challenges and monitored hits by rule, path, country and client, across all instances.
  • Rules without redeploys. Write rules and block IPs or countries in the dashboard. Every instance picks them up within a minute, signed with your project's own key.
  • Fleet-wide bans. A client banned by one server is banned by all of them.
  • False-positive tuning. Suggestions from real traffic, ready to paste into your config.
  • Alerts. Slack, Discord or any webhook on attack spikes, bans, confirmed injections and data leaks.
  • Emergency rules. Signed virtual patches for new CVEs, delivered to every instance.

The free Hobby plan is open now, with the dashboard, live events, unlimited events and IP or country blocks. Remote rules, fleet bans, tuning, alerts and emergency rules come with Pro, which isn't available yet.

Questions

Straight answers.

Is the library really free?

Yes. Every feature of the lightmoon package is MIT licensed and stays that way, including the CRS rules, bot checks, DDoS mitigation, response inspection and sink guards. LightMoon Cloud is the hosted part. Its Hobby plan is free; the paid plans, with remote rules, fleet-wide bans, alerts and the emergency rule feed, are not on sale yet.

Does Cloud add latency to my requests?

No. Decisions are made in your process. Events are batched and sent in the background, and rules are pulled once a minute and verified with your project's Ed25519 key. If the dashboard is unreachable, your instances keep the last rules they had.

What data leaves my servers?

Only blocked, challenged and monitored requests: method, host, path without the query string, the rules that matched, scores, country and the client IP truncated to its /24 or /48. Request bodies, headers, cookies and matched snippets are never sent. Bans send the banned network, so the other instances can apply it.

Does it replace Cloudflare or my CDN?

No, and it isn't meant to. A network provider absorbs volumetric floods that no middleware can. LightMoon covers the application layer, and it can hand its bans to Cloudflare so repeat offenders are stopped at the edge.

How accurate is it?

On open-appsec's WAF Comparison Project dataset (1,040,242 legitimate requests and 73,924 attacks) LightMoon with the CRS rules blocked 94.3% of attacks and 1.14% of legitimate requests. The benchmark page explains how we ran it and what the numbers don't show.

Protect the app, not just the edge.

Install the library in two minutes. Connect it to Cloud when you want one view of every instance.