Changelog
Release history and version updates for eslint-plugin-node-security
Live from GitHub
This changelog is fetched directly from CHANGELOG.md on GitHub and cached for 2 hours.
4.7.2
Patch Changes
- #364
86baa02Thanks @ofri-peretz! - Add the ecosystem and oxlint marks to the README logo row. Each plugin now leads with Interlace -> its ecosystem (node, nestjs, express, react, mongodb, postgresql, mysql, sqlite, prisma, drizzle, knex, typeorm, sequelize, lambda, vercel, jwt) -> oxlint -> ESLint; the generic quality plugins carry the row without an ecosystem mark. README-only change - no rule behaviour is affected. The patch bump is what carries the new README onto npm, which only refreshes a package README on publish.
4.7.1
Patch Changes
-
#338
dc25c81Thanks @ofri-peretz! - Re-publish every package so npm carries the optimised artifactNo source changed. This is a no-op patch whose entire purpose is to ship the artifact the current build already produces.
Manifests.
scriptsanddevDependenciesare now stripped from every publishedpackage.json. Neither can do anything in a consumer’s node_modules — npm never runs one and never installs the other — but they shipped in all 27 manifests, cluttered the npm page, and were read by SCA tools scanning installed manifests. No package declares a lifecycle hook, so nothing observable changes. Every published package is bumped so this applies uniformly rather than to a subset.Tarballs. 20 packages were last published before the build pipeline changed and still ship
AGENTS.md,CHANGELOG.md, JSDoc in the emitted.js, and the full generated.d.tstree:package published rebuilt saving eslint-plugin-react-features547 kB 320 kB −227 kB eslint-plugin-secure-coding653 kB 477 kB −176 kB eslint-plugin-conventions241 kB 116 kB −125 kB eslint-plugin-browser-security380 kB 291 kB −89 kB eslint-plugin-maintainability178 kB 116 kB −62 kB eslint-plugin-react-a11y232 kB 173 kB −59 kB eslint-plugin-reliability148 kB 90 kB −58 kB eslint-plugin-vercel-ai-security187 kB 130 kB −57 kB eslint-plugin-operability90 kB 43 kB −47 kB eslint-plugin-jwt140 kB 95 kB −45 kB eslint-plugin-modularity98 kB 58 kB −40 kB eslint-plugin-nestjs-security122 kB 86 kB −36 kB eslint-plugin-sqlite-security54 kB 20 kB −34 kB eslint-plugin-sequelize-security54 kB 21 kB −34 kB eslint-plugin-prisma-security52 kB 19 kB −33 kB eslint-plugin-mysql-security52 kB 19 kB −33 kB eslint-plugin-typeorm-security52 kB 19 kB −33 kB eslint-plugin-drizzle-security52 kB 19 kB −33 kB eslint-plugin-knex-security51 kB 19 kB −32 kB eslint-plugin-modernization45 kB 38 kB −7 kB Those 20 go from 3428 kB to 2169 kB — −36.7%. The remaining 7 were released after the pipeline change and only gain the manifest strip.
A new check in
scripts/check-published-artifacts.tsfails the build ifscriptsordevDependenciesever reappear in a published manifest, so the strip cannot silently regress.The dependency ranges did not need updating: every plugin pins
@interlace/eslint-devkitwith a caret that 1.6.0 satisfies, verified by a clean install of an unchanged plugin resolving devkit 1.6.0 with zero dependencies and notypescriptin the tree. -
Updated dependencies [
dc25c81]:- @interlace/eslint-devkit@1.6.1
4.7.0
Minor Changes
-
#313
1f4fc05Thanks @ofri-peretz! - Eight new rules closing the two fixable gaps found by the F#24/F#26 coverage benchmark (CWE Top 25 map + framework-depth matrix).Express — the helmet header family (the depth gap where SonarJS led 17 rules to our 14;
require-helmetonly proved the middleware was mounted, never that its protections were still on):no-disabled-helmet-protections(CWE-693) —helmet({ contentSecurityPolicy: false })and the rest of the disabled-default family, helmet 6 and 7 spellingsrequire-strict-transport-security(CWE-319) — HSTS disabled,max-agebelow the 180-day preload floor, orincludeSubDomains: falseno-unsafe-csp-directives(CWE-79 / 1021 / 311) —'unsafe-inline','unsafe-eval', wildcard sources,frame-ancestors '*', missingframe-ancestorsunderuseDefaults: false, andupgradeInsecureRequests: nullno-permissive-trust-proxy(CWE-348) —app.set('trust proxy', true), which makesreq.ipclient-controlled and every rate-limit bucket forgeable
Express — CWE Top 25 (2025) access-control adjacency (three of the four JS-applicable entries we did not cover):
require-route-authentication(CWE-306) — critical-function routes with no auth middleware and no principal read in the handlerno-client-controlled-authorization(CWE-863) —if (req.body.role === 'admin'): the check runs, and passes for anyone who sets the fieldno-idor-resource-access(CWE-639) —Invoice.findById(req.params.id)in a handler that never mentions the caller
Node — the fourth adjacency (CWE-77, generic command injection, previously covered only as CWE-78):
no-dynamic-command-string(CWE-77) — an assembled command string handed to a shell flag (spawn('bash', ['-c', …])) or to a command-runner that does not escape (execaCommand,$.raw)
In
recommended, the five structural rules ship aserror; the three access-control rules ship aswarn— their critical-path / authorization-attribute / lookup-method vocabularies are name-based, and naming heuristics never carry enforcement severity (plugin scope-audit invariant I3).
Patch Changes
4.6.0
Minor Changes
-
#305
8f1c9efThanks @ofri-peretz! - New ruleno-unsafe-buffer-alloc(CWE-908, Use of Uninitialized Resource) — closes a measured coverage gap againstsecurity-node/detect-buffer-unsafe-allocationand@microsoft/eslint-plugin-sdl/no-unsafe-alloc.It reports
Buffer.allocUnsafe()andBuffer.allocUnsafeSlow(), both of which return memory that was never zeroed, with a suggestion to swap inBuffer.alloc(). Neither the existingno-deprecated-buffer(deprecatedBuffer()constructor, CWE-676) norno-buffer-overread(read-side CWE-126) flagged the allocation itself.The rule is unconditional and does no dataflow — it does not try to prove the buffer is fully overwritten before it is read, so a correct
allocUnsafe+copypair is still reported. The one structural exemption isBuffer.allocUnsafe(n).fill(0), a parent-node check rather than variable tracking. Because of that false-positive profile it ships aswarninrecommendedrather thanerror(upstreamsecurity-nodeships its equivalent off by default).
Patch Changes
-
#317
5a8456bThanks @ofri-peretz! -no-ssrf: recogniseneedleas an HTTP client, soneedle.get(req.query.url)reports. The verb-firstneedle('get', url)form is still not covered — the rule only inspects the first argument. -
Updated dependencies [
09d2951]:- @interlace/eslint-devkit@1.4.4
4.5.0
Minor Changes
-
#310
28d7898Thanks @ofri-peretz! - Addno-timing-unsafe-compareto therecommendedpreset, restoring CWE-697 coverage.secure-coding/no-insecure-comparisonwas removed from everysecure-codingpreset, withnode-security/no-timing-unsafe-comparenamed as the replacement. But that rule was not in anyrecommendedpreset, so the practical result was that norecommendedpreset anywhere covered CWE-697 timing-unsafe comparison, and the migration note pointed users at a rule they would have had to enable by hand — which the note did not say.It enters at
'warn'rather than'error', matching the precedent already set byno-deprecated-bufferin this preset: adopters shouldn't have CI turn red on a version bump. Promote to'error'on the next major.Note the coverage now lives in a different package than before. A project that installs only
eslint-plugin-secure-codingand relied on its presets for this check needseslint-plugin-node-securityas well.A lock test in
src/index.test.tsfails if the rule leavesrecommendedagain, since that would silently make the migration note false. -
#288
89bea05Thanks @ofri-peretz! - Cut false positives in five security rules, measured against a 1,470-file corpus (webpacklib/, lodash, eslint-plugin-importsrc/, and two NestJS boilerplates).secure-coding/no-hardcoded-credentials— decide on the value, not the key name. The rule reported any string in a credential-named slot, soerrors: { password: 'incorrectPassword' }(an i18n error key) was a CVSS 9.8 finding — 5 of its 10 corpus hits. Detection is now driven by the value's shape: entropy, character-class mix, charset, and a "natural word string" test that rejects identifier- and message-shaped values. A credential-shaped name is still consulted, but only to promote an already-secret-shaped value. Corpus: 10 → 7 findings, and all 7 are true positives — including two the old logic missed, because a 25-character randomkey:is now found by shape rather than by being on a name allowlist.secure-coding/no-unsafe-deserialization—setTimeoutis not a deserializer.await new Promise(resolve => setTimeout(resolve, 1000))was rated CVSS 9.8 CRITICAL.setTimeout/setIntervalnow only report in their implied-evalform (string first argument), and calls inside a function nameddeserialize/unserialize/fromJSON/fromBuffer— a class implementing a serialization protocol — are exempt. Corpus: 35 → 4.secure-coding/no-graphql-injection— require real GraphQL syntax. Any template literal containing a nested brace or the wordtypewas a CVSS 9.8 GraphQL injection. Operation and schema keywords must now start a line, schema keywords require a body, and a bare selection set must be the entire string. Concatenations are matched on their reassembled static value rather than on their source text. Corpus: 41 → 0.node-security/require-secure-deletion— only sensitive properties. The rule fired on everydelete obj.prop. It now reports only a statically known, sensitive property name (password,token,apiKey,privateKey,sessionId, …), configurable via the newadditionalSensitivePropertiesoption, and understands computed access and optional chaining. Corpus: 25 → 1 (a genuinedelete userDto.oldPassword).secure-coding/no-insecure-comparison— removed fromrecommended,recommended-strictandowasp-top-10. It is deprecated in favour ofnode-security/no-timing-unsafe-compare, and its loose-equality half re-reports coreeqeqequnder a CWE-697 banner — 433 corpus findings, all duplicates. No narrowing fixes that, so the honest change is to stop switching it on for people; it remains exported and available viastrictor explicit opt-in. Its timing-attack half was also narrowed to match secret keywords on identifier word segments instead of substrings of the whole expression text, which stopsif (key === "__non_webpack_require__")(andmonkey,keyword,machine,author) from being reported: 443 → 221.
Patch Changes
-
#294
659f6dcThanks @ofri-peretz! - Rewritedescriptionandkeywordson every published package for npm search discovery. npm ranks on name, description, and keywords, and the registry only picks up these fields at publish — so this is metadata-only and takes effect for each package on its next release.Descriptions now lead with the search phrase. Every one starts
ESLint plugin for <the thing you'd search>instead of a brand-first or category-first framing, and names the concrete vulnerabilities the plugin actually detects. Three were corrected while doing so:eslint-plugin-import-nextclaimed "100x faster no-cycle detection". No 100x measurement exists:CLAIMS.mdrecords 3.1x end-to-end (8x in pure rule execution) on a 5,483-file React codebase, and the highest number in any benchmark result is 54.9x on the synthetic corpus. The description now states the real-codebase figure.eslint-plugin-secure-codingclaimed SQL injection, XSS and CSRF coverage — none of which are its rules. It now names what it does detect: LDAP, XPath, XXE, GraphQL and template injection, unsafe deserialization, ReDoS, missing authentication, and PII in logs.eslint-plugin-secure-coding("89 rules") andeslint-plugin-react-a11y("37 rules") hard-coded rule counts that had drifted from reality. Counts are generated intointerlace-numbers.json; hand-typed copies are removed rather than corrected.
Keywords now match the vocabulary of the plugins that rank.
eslint-plugin-security,eslint-plugin-jsx-a11y,eslint-plugin-nandeslint-plugin-importall carry theeslint/eslintplugin/eslint-plugintrio — six of our packages were missingeslintplugin, and every one now carries all three plusstatic-analysis,lintingandcode-quality. Security plugins addsast,appsecandvulnerability;node-securityandsecure-codingalso carrynodesecurity, the exact keywordeslint-plugin-securityranks on. Each plugin gained the CWE identifiers and attack names for what it detects (cwe-78command injection,cwe-22path traversal,cwe-89SQL injection,cwe-79XSS,cwe-347JWT algorithm confusion,cwe-352CSRF,cwe-943NoSQL injection), andnode-securitygained the crypto vocabulary it had been missing entirely despite absorbing the crypto rule set (crypto,cryptography,weak-hash,md5,sha1,timing-attack).No rule behavior, exports, or configuration changes.
-
#296
0c7a208Thanks @ofri-peretz! - Cut two false positives confirmed against the benchmark corpus SAFE fixtures.node-security/no-ssrf— the user-input gate only ran when the URL argument was a bare identifier, so every other shape reported unconditionally. A Node options object built from a helper's own parameters —https.request({ host, path, method: 'GET' }), frombenchmarks/corpus/CWE-444/safe/request-default-parser.js— was flagged with no user data anywhere in the flow.The gate now applies to every argument shape and requires evidence: a user-input-named identifier standing as the URL, a read off a request object (
req/request/ctx/event), or a template literal or concatenation interpolating either. Options-object fields count when they are request-sourced, or when aurl/href/urikey holds a user-input-named identifier.Newly ignored: options objects and interpolations built purely from locals. Still reported:
fetch(userUrl),fetch(req.query.url),https.request({ host: req.query.host }),fetch(`https://${userHost}/x`).secure-coding/no-hardcoded-credentials—secret: '<your-secret-here>'frombenchmarks/corpus/CWE-798/safe/test-placeholder-values.jswas reported at CVSS 9.8. The angle brackets are two character classes, which is all the shape gate asks for once the slot is credential-named.Self-evident placeholders are now skipped: bracketed template slots (
<…>,{{…}},${…},[…]), placeholder words standing as their own token (changeme,YOUR_API_KEY,example), and one character repeated (xxxxxxxxxxxx). Whole-token matching only, so a real secret that merely contains such a substring is unaffected.The allowlist applies to non-structural findings only — a JWT, an
sk_live_key, or apostgres://user:pass@hoststring still reports whatever words it contains. Set the newallowPlaceholders: falseoption to restore the previous behaviour. -
Updated dependencies [
e1cdf83,659f6dc]:- @interlace/eslint-devkit@1.4.3
4.4.3
Patch Changes
-
#269
7028fe2Thanks @ofri-peretz! - docs: dual-logo README header (Interlace mark + ESLint mark side by side) and closing Interlace footer — refreshes the README rendered on npmjs.com. No runtime changes. -
Updated dependencies [
7028fe2]:- @interlace/eslint-devkit@1.4.2
4.4.2
Patch Changes
- #252
d67e395Thanks @ofri-peretz! - Fix Codecov badge showing "unknown" — switch from flag to component URL format
4.4.1
Patch Changes
- #225
34ff5a8Thanks @ofri-peretz! - CI-only: pin all coverage thresholds at 100% (integration target, merges last).
4.4.0
Minor Changes
-
#190
6bb476dThanks @ofri-peretz! - feat(node-security): addno-dynamic-algorithm-selection(CWE-327)Disallow dynamic (non-literal) algorithm names in Node.js crypto functions. A runtime-selected algorithm argument can allow a downgrade to a broken or risky cryptographic algorithm (CWE-327: Use of a Broken or Risky Cryptographic Algorithm). AST-structural — flags non-literal algorithm arguments to the crypto APIs.
Patch Changes
-
#215
f42ea93Thanks @ofri-peretz! - Alignno-dynamic-algorithm-selection'smeta.docs.cvss(7.4) to the CVSS its finding actually emits. The rule's message carriesCWE-327and sets no per-messagecvss, so it inheritsCWE_MAPPING['CWE-327']= 7.5 viaenrichFromCWE— docs now match the emitted value. Surfaced by the cross-pluginsecurity-cvss-docs-consistency.lock.test.tslock (added in #213), which turned main red when this rule landed concurrently with the CVSS sweep. Documentation-metadata only; no emitted finding changes. -
#213
391dbe6Thanks @ofri-peretz! - Align every security rule'smeta.docs.cvssto the CVSS its finding actually emits. The emitted machine-readable message sources itsCVSS:xfromCWE_MAPPINGviaformatLLMMessage→enrichFromCWE, but the staticmeta.docs.cvssdocumentation field had drifted on 45 rules across these 7 plugins — e.g.no-hardcoded-credentialsdocumented9.5while emittingCVSS:9.8(the value the published article and SARIF/LLM consumers already read).This corrects the documentation metadata only — no emitted finding changes. Locked by
security-cvss-docs-consistency.lock.test.ts(cross-plugin: every security rule'smeta.docs.cvssmust equal the CVSS it emits), theno-hardcoded-credentialsrule lock (real ESLintLinteremission), and a devkitenrichFromCWEcontract test pinningCWE-798 → 9.8.Follow-up (not in scope): 50 security rules document a CVSS that never appears in any emitted message (their messages carry no CWE), and several rules emit the generic CWE score where a rule-specific score may be warranted — both change emitted output and are separate decisions.
4.3.0
Minor Changes
-
#148
82718c2Thanks @ofri-peretz! - feat(node-security): addno-math-random-crypto(CWE-338)Detects
Math.random()used in cryptographic contexts (tokens, keys, secrets, salts, IVs, session IDs) and steers tocrypto.randomBytes()/crypto.randomUUID().This was the one cryptography rule that the deprecated
eslint-plugin-cryptoshipped but had not been carried intonode-securityduring the 2026-05 consolidation — soeslint-plugin-crypto's deprecation notice ("node-security includes all cryptography rules") was previously inaccurate. It is now true.Added to the
recommendedpreset aserror. The detection is return/assignment context-aware (matchescrypto-named variables, properties, and function returns) so benign uses like a Fisher-Yates shuffle into a non-crypto variable do not false-positive — verified against the fn-fp benchmark (40/40 detection, 0 false positives with the crypto-free fleet).
Patch Changes
-
#144
8843ce7Thanks @ofri-peretz! - fix: ILB-Wild FP reduction + doc examples + doc-test-alignment scanner fixesno-unlimited-resource-allocation— FP reduction (430 Edge FPs)- Skip loop-allocation reporting when the first argument is a numeric literal (e.g.
Buffer.alloc(1024)inside a loop is statically bounded, not a risk) - Skip
Array.isArray,Array.from,Array.ofcalls in thealloc/Arraypattern check (these don't allocate unbounded memory)
no-hardcoded-credentials— FP reduction (~280 Edge FPs)- Extended test-file skip to cover
.fixture.,.mock.,__mocks__/,/tests/,/fixtures/,/mocks/paths - Skip string literals that are fallback values in
process.env.X || 'fallback'expressions — the secret lives in the environment, the string is only a dev-mode default
Doc examples — 4 rules now have ❌ Incorrect examples
lambda-security/no-missing-authorization-checklambda-security/no-overly-permissive-iam-policynode-security/prefer-native-crypto(renamed non-standard### ❌ Third-Party (Flagged)to### ❌ Incorrect)vercel-ai-security/require-tool-confirmation(replaced placeholder with a real tested example)
ilb-doc-test-alignmentscanner fixes- Accept both
## ❌and### ❌headings (docs use H3 under an H2## Examplessection; was only finding H2) - Slice from end-of-line rather than end-of-regex-match (prevents
## ❌ Incorrect Codefrom leaving a partial heading in the parsed section)
Result:
ilb:doc-test-alignment→ 206 ok, 0 doc has no ❌ examples (was 165 missing). - Skip loop-allocation reporting when the first argument is a numeric literal (e.g.
-
#141
38ab670Thanks @ofri-peretz! - fix: remove falsemeta.fixable: 'code'declarations from 21 rules that had nofix()functionRules that declared
fixable: 'code'in their ESLint meta without an actualfix()implementation would show the ⚡ auto-fix icon in editors and CI formatters but apply no change when--fixwas run. This patch removes the misleading declaration from:browser-security/no-clickjackingimport-next/first,named,no-barrel-import,no-import-module-exports,no-namespacenode-security/no-buffer-overread,no-unsafe-dynamic-require,no-zip-slipreact-features/react-no-inline-functionsreliability/no-jsdoc-terminator-in-example(usessuggest, not auto-fix; corrected tohasSuggestions: trueonly)secure-coding/no-directive-injection,no-electron-security-issues,no-graphql-injection,no-improper-sanitization,no-improper-type-validation,no-ldap-injection,no-unchecked-loop-condition,no-unlimited-resource-allocation,no-weak-password-recovery,no-xpath-injection
-
#186
edf208dThanks @ofri-peretz! - Consolidation cleanup — no rule behavior change:- react-features: the README rules table now lists the 8
componentApipreset rules. The README generator (sync-readme-rules.ts) and theplugin-rule-source-driftvalidator now recurse into nesteddocs/rules/<category>/subfolders, so every documented rule is advertised consistently (previously the nested componentApi docs were silently dropped, which an earlierreadmeexception had papered over — that exception is now removed in favour of the real fix). - node-security: remove the orphaned
no-pii-in-logsrule source — the rule was migrated toeslint-plugin-secure-codingand is no longer exported here; the dead source was still compiling intodist. - import-next: restore the
no-cycleunit test after #180's SCC refactor (computeSCCsFromFile+findShortestCyclePathare now bridged in the mock).
Also fixes
scripts/ilb-plugin-scope-audit.tsto stop mis-reading config-preset keys ('recommended-strict': {) as rules. - react-features: the README rules table now lists the 8
-
#148
82718c2Thanks @ofri-peretz! - feat+fix: ILB-Wild FP reduction + two new quality rulesno-unsafe-deserializationFP reduction (~112 FPs)- Track
fs.readFileSync('literal')calls inliteralPathFileVars— a file read with a hardcoded path (bundled config) is not user-controlled input for safe deserializers (JSON.parse, schema-validating parsers).eval()still fires even on literal-path reads.
no-buffer-overreadFP reduction (~129 FPs)- Remove
b(single-char, too broad) andchunk(too common for array chunks) from the Buffer alias heuristic —isBufferTypenow only matchesbufandbytesby name, reducing false matches on non-Buffer variables.
New rule:
modernization/prefer-template-literal- Flags
"string " + variableconcatenation and suggests the equivalent template literal. - Auto-fix produces the correct
`string ${variable}`replacement. - Pure string literal chains (
"a" + "b") and numeric addition are not flagged. - Closes P2 quality FN
prob_string_concatin the ILB-Arena-Quality bench.
New rule:
modularity/no-mutable-exports- Flags
export letandexport var— module exports should be immutableconstbindings so all importers share a stable reference. - Auto-fix replaces
let/varwithconst. - Closes P2 quality FN
prob_mutable_exportin the ILB-Arena-Quality bench.
- Track
-
Updated dependencies [
736a5fe]:- @interlace/eslint-devkit@1.4.1
[4.1.0] - 2026-05-03
Added
- New rule
no-deprecated-buffer— flags use of the deprecatedBuffer()constructor (Node.js security advisory;Buffer.from/Buffer.allocshould be used instead). Enabled in therecommendedpreset atwarnto avoid breaking adopters with legacyBuffer()calls; will be promoted toerrorin the next major.
Bug Fixes
no-zip-slip: removed redundant dangerous-destination check from the literal handler. Extraction-call handler already reportsdangerousArchiveDestination; the literal-side check was producing duplicate errors and (separately) firing on unrelated calls likefs.readFileSync('/etc/app/config').lock-file,detect-child-process: minor refinements (see source diff).
[4.0.4] - 2026-02-08
Bug Fixes
- align codecov component IDs with full package names (2831b968)
- resolve all benchmark FN/FP across security rules (45ffb791)
- rules: reduce false positives across security rules (c192233c)
Documentation
- fix changelog header format across all packages (c3a15082)
❤️ Thank You
- Ofri Peretz
[4.0.3] - 2026-02-06
Bug Fixes
- ⚠️ rules: reduce false positives across security rules (af4ca0e7)
- align codecov component names and update docs components (0a59a86c)
⚠️ Breaking Changes
- rules: Some previously flagged patterns are now correctly allowed (af4ca0e7)
❤️ Thank You
- Ofri Peretz
[4.0.2] - 2026-02-02
This was a version bump only for eslint-plugin-node-security to align it with other projects, there were no code changes.
Changelog
All notable changes to eslint-plugin-node-security will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Documentation
- 📘 Launched new documentation site: eslint.interlace.tools
- 📝 Achieved 100% documentation parity (both .md and .mdx files)
[4.0.1] - 2026-02-02
This was a version bump only for eslint-plugin-node-security to align it with other projects, there were no code changes.
[4.0.0] - 2026-02-02
This was a version bump only for eslint-plugin-node-security to align it with other projects, there were no code changes.
[1.0.0] - 2026-01-26
Added
- Initial stable release with 31 Node.js security rules
- LLM-optimized error messages with CWE references and OWASP mapping
- 100% test coverage across all rules
- ESLint 8 and ESLint 9 flat config support
- TypeScript type definitions for all rule options
Rule Categories
Cryptography Rules (12)
no-sha1-hash- Disallow SHA-1 for security-sensitive operations (CWE-328)no-weak-hash-algorithm- Disallow MD5, SHA-1 for cryptographic hashing (CWE-328)no-ecb-mode- Disallow ECB mode for block ciphers (CWE-327)no-static-iv- Disallow static initialization vectors (CWE-329)no-insecure-key-derivation- Require secure key derivation functions (CWE-916)no-insecure-rsa-padding- Require OAEP padding for RSA (CWE-780)no-self-signed-certs- Detect disabled TLS certificate validation (CWE-295)no-timing-unsafe-compare- Require timing-safe comparison for secrets (CWE-208)no-cryptojs- Prefer native crypto over CryptoJS (CWE-327)no-cryptojs-weak-random- Disallow CryptoJS weak random (CWE-338)no-deprecated-cipher-method- Disallow deprecated crypto methods (CWE-327)prefer-native-crypto- Prefer Node.js native crypto module
File System Rules (7)
no-path-traversal- Prevent path traversal attacks (CWE-22)no-unsafe-file-permissions- Enforce secure file permissions (CWE-732)no-symlink-attacks- Prevent symlink-based attacks (CWE-59)require-file-validation- Require file type validation (CWE-434)no-temp-file-exposure- Prevent temp file security issues (CWE-377)no-hardcoded-paths- Prevent hardcoded sensitive paths (CWE-426)require-safe-path-join- Require path.join for path construction (CWE-22)
Process & Shell Rules (6)
no-child-process-injection- Prevent command injection (CWE-78)no-shell-exec- Disallow shell: true in spawn options (CWE-78)no-env-exposure- Prevent environment variable exposure (CWE-214)require-process-sanitization- Require input sanitization for process args (CWE-88)no-unsafe-exec- Disallow exec with dynamic input (CWE-78)no-eval-alternatives- Disallow Function constructor, vm runInContext (CWE-95)
Network Rules (6)
require-tls-verification- Require TLS certificate validation (CWE-295)no-dns-rebinding- Prevent DNS rebinding attacks (CWE-350)no-ssrf- Prevent Server-Side Request Forgery (CWE-918)require-https- Require HTTPS for external requests (CWE-319)no-unsafe-redirect- Prevent open redirects (CWE-601)require-host-validation- Require host header validation (CWE-20)
Presets
recommended- Balanced security for Node.js applicationsstrict- All rules as errorscrypto- Cryptography-focused subsetfilesystem- File system security subsetnetwork- Network security subset
Features
- Comprehensive detection patterns for Node.js core modules
- Support for popular libraries (fs-extra, glob, rimraf)
- Auto-fix capabilities where safe
- ESLint MCP integration for AI assistants
View on GitHub →
Building secure JavaScript with Interlace? Star the repo to get new rules and CWE coverage as we ship them — or follow the AI-code-security benchmarks behind them.