DEV Community

Cover image for eslint-plugin-security Is the 14-Rule Generic Floor. Here's the Domain Depth to Layer on Top.
Ofri Peretz
Ofri Peretz

Posted on • Edited on • Originally published at ofriperetz.dev

eslint-plugin-security Is the 14-Rule Generic Floor. Here's the Domain Depth to Layer on Top.

eslint-plugin-security is the foundational JavaScript security linter — 2.4M+
weekly downloads
, actively maintained (4.0.0 shipped February 2026, adding
detect-bidi-characters for Trojan-Source attacks). Its 14 rules are the
generic floor every Node project should have.

The honest framing isn't "replace it" — it's that 14 generic rules are a
floor, not a ceiling. They catch the cross-cutting classics; they aren't
built for the depth of SQL, JWT, crypto, or AI-agent security. The move is to
layer domain rules on top. Here's exactly what the floor covers, what it
doesn't, and how to run both.

What the 14 rules cover (the generic floor)

detect-child-process, detect-eval-with-expression, detect-non-literal-require,
detect-non-literal-fs-filename, detect-non-literal-regexp,
detect-unsafe-regex, detect-object-injection, detect-possible-timing-attacks,
detect-pseudoRandomBytes, detect-buffer-noassert, detect-new-buffer,
detect-disable-mustache-escape, detect-no-csrf-before-method-override,
detect-bidi-characters.

These are real, valuable, language-level checks — command injection, eval, unsafe
regex, the object-injection sink, timing comparisons. Every Node app benefits.

What a generic floor can't reach

On a fixture of 12 Node vulnerability classes, eslint-plugin-security flagged
21 issues; the domain plugins flagged 46 (measured — see
the 4-way benchmark).
The 25-finding gap is domain depth a generic ruleset has no rule for:

Domain What's missing from a generic linter The layer that adds it
PostgreSQL SQL injection, connection leaks, COPY exploits eslint-plugin-pg (13 rules)
JWT / auth alg:none, algorithm confusion, claim validation eslint-plugin-jwt (13 rules)
Crypto & system weak hashes, ECB/static-IV, SSRF, zip-slip eslint-plugin-node-security (34 rules)
Browser / DOM CSP, CORS, innerHTML, JWT-in-storage eslint-plugin-browser-security (45 rules)
AI / LLM prompt injection, tool-call agency eslint-plugin-vercel-ai-security (19 rules)

There's also a precision difference: on validated-safe code,
eslint-plugin-security produced 5 false positives in that benchmark
(detect-object-injection on allowlist-validated keys, detect-non-literal-fs-filename
on path-validated reads) — it pattern-matches the sink without seeing the guard.
The domain rules carry CWE/OWASP/CVSS metadata and AST-aware validation detection.

The layering pattern

You don't have to choose. Keep the generic floor for the classics, add domain
plugins where your stack needs depth:

// eslint.config.mjs — `configs` is a NAMED export on the Interlace plugins
import security from "eslint-plugin-security";
import { configs as secureCoding } from "eslint-plugin-secure-coding";
import { configs as nodeSecurity } from "eslint-plugin-node-security";
import { configs as pg } from "eslint-plugin-pg";
import { configs as jwt } from "eslint-plugin-jwt";

export default [
  security.configs.recommended, // your existing eslint-plugin-security — the generic floor (14 rules)
  secureCoding.recommended, // general OWASP source patterns
  nodeSecurity.recommended, // crypto, supply-chain, SSRF
  { files: ["**/db/**"], ...pg.recommended }, // PostgreSQL depth
  jwt.recommended, // auth depth
  // + browser-security (DOM/CSP) and vercel-ai-security (LLM) where your stack uses them
];
Enter fullscreen mode Exit fullscreen mode

(The layering config keeps your already-installed eslint-plugin-security; the
install below adds the domain layers.)

Or migrate the general layer to eslint-plugin-secure-coding (27 rules, OWASP-mapped):

npm install --save-dev eslint-plugin-secure-coding eslint-plugin-node-security eslint-plugin-pg eslint-plugin-jwt
Enter fullscreen mode Exit fullscreen mode

Where OWASP fits

For the full picture of which OWASP Top 10 categories static analysis genuinely
covers — and the two it honestly can't — see
the OWASP Top 10 mapping
(it's 8 of 10, not "100%"). The point isn't a coverage scoreboard; it's matching
rule depth to your stack's real attack surface.

A note on the incumbent

eslint-plugin-security pioneered JavaScript security linting and is still the
right baseline — 2.4M downloads, an eslint-community-maintained project that
shipped a major version in 2026. This isn't a teardown; it's the case for
layering domain depth on a solid floor.


Compatibility

The domain layers ship the same contract:

Surface Support
Package managers npm, yarn, pnpm, bun
Node >= 18.0.0
ESLint `^8.0.0 \
Module system Plugins ship CommonJS; your config can be {% raw %}eslint.config.js or .mjs
Oxlint flagship rules run via the interlace-* ports, parity-gated in CI

Links

⭐ Star on GitHub if your stack needs more security depth than a generic floor.


I'm Ofri Peretz, a security engineering leader and the author of the
Interlace ESLint ecosystem — domain-specific static analysis for security,
reliability, and performance on the Node.js stack.

ofriperetz.dev · LinkedIn · GitHub

Top comments (0)