DEV Community

Cover image for SonarJS Has 269 Rules and Found 13 Security Issues Where the Domain Plugins Found 46 — It's a Quality Linter
Ofri Peretz
Ofri Peretz

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

SonarJS Has 269 Rules and Found 13 Security Issues Where the Domain Plugins Found 46 — It's a Quality Linter

eslint-plugin-sonarjs is one of the best linters in the ecosystem — 269 rules,
3M+ weekly downloads, SonarSource's analysis engine distilled into ESLint. So I
ran it against a file of 12 vulnerability classes alongside the Interlace
security plugins. SonarJS flagged 13 security issues on that file; the domain
plugins flagged 46 (different finding counts on the same file — not a shared
scorecard).

That's not a knock on SonarJS. It's a scope result: SonarJS is a quality
linter that happens to carry a handful of security rules. Security depth is a
different product. Here's the reproducible data, and why "use both" is the real
answer.

Detection — vulnerable.js (12 vulnerability classes)

Config Engine Security findings
Oxlint built-in Oxlint 1
Interlace flagship rules Oxlint 5
eslint-plugin-sonarjs (recommended) ESLint 13
eslint-plugin-security (recommended) ESLint 21
Interlace (4 plugins, recommended) ESLint 46

SonarJS's 13 came from exactly the rules it ships for cross-language security
basics: sonarjs/os-command (×3) + no-os-command-from-path (×1),
sonarjs/sql-queries (×2), sonarjs/code-eval (×2), sonarjs/slow-regex (×2),
sonarjs/hashing (×2), sonarjs/pseudo-random (×1). Those are genuinely good
rules — os-command in particular is best-in-class. The same run also produced
25 quality findings (no-unused-vars, no-dead-store, …) — which is the
point: SonarJS spends its 269 rules on quality, and a few of them overlap
security.

The Interlace plugins surfaced 33 more findings — the Node-specific
depth
SonarJS has no rule for: fs-path traversal
(node-security/detect-non-literal-fs-filename), object injection /
prototype-pollution (secure-coding/detect-object-injection), PostgreSQL
injection (pg/no-unsafe-query), unsafe deserialization
(secure-coding/no-unsafe-deserialization), DOM XSS
(browser-security/no-innerhtml), insecure comparisons, and more.

False positives — safe-patterns.js

Config False positives
eslint-plugin-sonarjs 0 (security)
Oxlint built-in 0
Interlace @ Oxlint 0
Interlace @ ESLint 3 (a perf rule + a conservative-by-design rule)
eslint-plugin-security 5 (genuine — validated-key + path-validated)

SonarJS is precise — its 10 findings on the safe file were all quality
(no-unused-vars), zero security false alarms. That precision is part of why
it's a great quality tool.

Where SonarJS is the right call

  • Cognitive complexity — one of the best implementations anywhere.
  • Dead code / unused assignments / redundant logic — the no-dead-store, no-unused-collection, all-identical-comparison family.
  • Code smells — duplicate branches, collapsible conditionals.
  • The security basics — command injection, eval, weak hashing, insecure randomness, the SQL-string and slow-regex patterns above.

Where you need domain security rules

SonarJS has no rule for the Node-specific attack surface: fs path traversal,
prototype pollution, NoSQL/Mongo injection, SSRF, open redirect, timing attacks,
JWT claim validation, unsafe deserialization. Those are the gaps the
domain plugins fill — not because SonarJS is weak, but because it was built for
the breadth of JavaScript quality, not the depth of Node.js security.

The real answer: run both

SonarJS for quality, the domain plugins for security. They don't overlap enough
to conflict, and together they cover both axes:

// eslint.config.mjs
import sonarjs from "eslint-plugin-sonarjs";
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 browserSecurity } from "eslint-plugin-browser-security";

export default [
  sonarjs.configs.recommended, // quality
  secureCoding.recommended, // general security
  nodeSecurity.recommended, // crypto, supply-chain, SSRF, fs
  pg.recommended, // PostgreSQL
  browserSecurity.recommended, // DOM / browser
];
Enter fullscreen mode Exit fullscreen mode

Methodology — reproduce it

Honest disclosure: the fixtures are team-authored (vulnerable.js, 12
vulnerability classes; safe-patterns.js, validated-safe patterns), so they
measure coverage of the surface the Interlace rules target — run it on your own
code for an unbiased read. Versions (measured 2026-05): eslint@9.39,
oxlint@1.67, eslint-plugin-sonarjs@4.0.3 (269 rules),
eslint-plugin-secure-coding@3.2.0, node-security@4.2.0, pg@1.4.3,
browser-security@1.2.3. Each plugin's recommended preset, --format json,
counted by ruleId (security rule IDs for the security totals).

npm i -D eslint@9 oxlint eslint-plugin-sonarjs eslint-plugin-secure-coding \
  eslint-plugin-node-security eslint-plugin-pg eslint-plugin-browser-security
npx eslint --config eslint.config.sonarjs.mjs test-files/vulnerable.js --format json
npx eslint --config eslint.config.interlace.mjs test-files/vulnerable.js --format json
npx oxlint test-files/vulnerable.js   # Oxlint built-in row
Enter fullscreen mode Exit fullscreen mode

(On ESLint 8, set ESLINT_USE_FLAT_CONFIG=true to load eslint.config.mjs;
ESLint 9+ uses flat config by default. The Interlace-flagship-on-Oxlint row is
reproduced from the repo per the 4-way benchmark.)

The full 4-engine version of this benchmark (ESLint + Oxlint, built-in + plugins)
is in the security-linter benchmark.


Compatibility

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 Interlace flagship rules run via the interlace-* ports, parity-gated

Links

⭐ Star on GitHub if you run SonarJS for quality and want the security half to match.


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)