Skip to Content

Security

Security-focused TypeScript source rules from eslint-plugin-security.

Reports likely security smells that warrant human review even if no exploit is statically provable: non-literal sinks for eval, file I/O, regex construction, child-process spawning, and cryptographic primitives.

Treat findings as hints, not proofs.

Source: eslint-plugin-security@4.0.0 (Apache-2.0, distribution requires propagating the upstream NOTICE attribution).

Rule index

Each rule name links to the detailed section below.

Examples come from the checked lint corpus  or package-level rule tests when project layout matters.

Rules

security/detect-bidi-characters

Detect Trojan-Source bidi control characters (U+202A, U+202E, …) hidden inside source.

Example:

const safe = "user"; // reports: security/detect-bidi-characters (error) const access = "user‮";

security/detect-buffer-noassert

Detect Buffer reads/writes called with noAssert = true, which skips Node’s offset/length bounds checks.

The flag lets the offset slide past the buffer end and read unrelated memory, so production code should never set it.

Example:

const buffer = Buffer.alloc(8); buffer.readDoubleLE(0, false); // reports: security/detect-buffer-noassert (error) buffer.readDoubleLE(0, true);

security/detect-child-process

Detect any import of child_process and any exec/execSync call whose command argument is not a string literal.

Non-literal commands are the canonical shell-injection sink in Node services.

Example:

// reports: security/detect-child-process (error) require("child_process").exec(command);

security/detect-disable-mustache-escape

Detect assignments setting escapeMarkup = false (or the equivalent option on Handlebars/Mustache-style engines), which turns off HTML entity escaping in template output.

Result: an unguarded XSS sink for caller-controlled strings.

Example:

escapeMarkup = false; // reports: security/detect-disable-mustache-escape (error) view.escapeMarkup = false;

security/detect-eval-with-expression

Detect eval(...) calls whose argument is not a string literal.

Any expression argument means caller-controlled data can reach a code-execution sink. The rule flags the call shape, not proven taint.

Example:

eval("alert()"); // reports: security/detect-eval-with-expression (error) eval(userInput);

security/detect-new-buffer

Detect new Buffer(input) constructions with non-literal input, historical source of allocation-disclosure bugs.

The three APIs that replaced it are offered as editor suggestions: Buffer.from, Buffer.alloc, and Buffer.allocUnsafe. None is applied automatically. Which one is correct depends on what the argument turns out to be, and this rule fires precisely when the argument is not a literal, so the source cannot say. Choosing for the author is how the constructor’s original hazard returns: Buffer.allocUnsafe applied to what was really a string hands back uninitialized heap memory.

The finding stays untagged even though Node deprecated its global constructor in DEP0005. This rule mirrors the upstream syntax-only match, which can also report a user-defined constructor named Buffer; a rule-level Deprecated tag would stamp that application constructor too.

Example:

new Buffer("safe"); // reports: security/detect-new-buffer (error) new Buffer(input);

security/detect-no-csrf-before-method-override

Detect Express applications mounting csrf middleware before methodOverride, which lets the CSRF token be bypassed.

Example:

express.methodOverride(); express.csrf(); // reports: security/detect-no-csrf-before-method-override (error) express.methodOverride();

security/detect-non-literal-fs-filename

Detect fs calls (readFile, writeFile, createReadStream, …) whose filename argument is not a string literal.

Dynamic filenames are the standard path-traversal sink; sanitise or allow-list before the call.

Example:

import fs from "fs"; fs.readFileSync("./safe.json"); // reports: security/detect-non-literal-fs-filename (error) fs.readFileSync(filename);

security/detect-non-literal-regexp

Detect new RegExp(...) construction whose pattern argument is not a string literal.

Caller-controlled patterns can both trigger catastrophic backtracking and let an attacker reshape the matcher to bypass intended validation.

Example:

new RegExp("^[a-z]+$"); // reports: security/detect-non-literal-regexp (error) new RegExp(pattern);

security/detect-non-literal-require

Detect require(...) calls whose specifier is computed at runtime.

A dynamic specifier lets caller-controlled data choose the module to load, bypassing any module allow-list on Node.

Example:

require("node:fs"); // reports: security/detect-non-literal-require (error) require(moduleName);

security/detect-object-injection

Detect dynamic bracket-access such as obj[req.body.x] = ..., which can let caller-controlled keys overwrite prototype-shaped properties or pull out unintended fields.

Fires on virtually any computed property access; expect a high false-positive rate in normal application code.

Example:

object["safe"]; // reports: security/detect-object-injection (error) object[key];

security/detect-possible-timing-attacks

Detect direct equality comparisons involving secret-like identifiers (if (token === expected)), use crypto.timingSafeEqual instead.

Example:

if (age === 5) { } // reports: security/detect-possible-timing-attacks (error) if (password === "mypass") { }

security/detect-pseudoRandomBytes

Detect crypto.pseudoRandomBytes, which produces values that are not cryptographically secure.

Tokens, session ids, and key material must use crypto.randomBytes (or Web Crypto’s getRandomValues) instead.

Type-aware via the Checker, which resolves the object at the use site so an automatic rewrite never lands on a shadowed binding. Enabling this rule puts the whole run on the checker path; the diagnostic itself stays name-based and still reports without one.

Node deprecated the name in DEP0115 and the member name alone is rewritten to randomBytes, so the API is repaired whether it is called or passed around as a value. The rename is automatic when the source proves crypto is an import or require of Node’s crypto / node:crypto module. A name-only match gets the same edit as an editor suggestion instead, because a local application object can also be named crypto.

The rule stays untagged for that same reason. Diagnostic tags are rule-level, so Deprecated would also strike through a reported member on a user-defined crypto object.

Example:

crypto.randomBytes; // reports: security/detect-pseudoRandomBytes (error) crypto.pseudoRandomBytes;

security/detect-unsafe-regex

Detect regex literals with catastrophic backtracking potential (ReDoS), typically nested or overlapping quantifiers over the same character set.

Matching caller-controlled input against such a pattern can block the event loop for seconds.

Example:

/^d+1337d+$/; // reports: security/detect-unsafe-regex (error) /(x+x+)+y/;
Last updated on