JavaScript and TypeScript code review has a peculiar shape: the linting tools are outstanding and universally adopted, but linting is not security, and the ecosystem's real risk lives in the dependency graph — a node_modules tree that routinely runs to tens of thousands of packages. So the tooling question splits three ways: keep the code clean (ESLint, Biome, the type checker), find vulnerabilities in the code you wrote (SAST), and control the enormous surface you pulled in from npm (SCA). This guide covers all three honestly and names the 2026 tools that matter.
What to look for
- Linting is table stakes, not security. ESLint catches bugs and enforces style. It does not, by itself, find injection or prototype-pollution exploits. Do not confuse a green lint run with a secure app.
- TypeScript's type system is a real defense. Strict mode eliminates a category of runtime errors and some injection paths. Turning on
strictis one of the highest-leverage moves available. - Cross-file taint. Vulnerabilities flow from an Express route through middleware into a query. Single-file matchers miss this; you need taint analysis.
- The npm surface. Most of your shipped code is dependencies, and npm is the most actively attacked package registry. Real-time package-risk and SCA are essential.
- Framework and full-stack awareness. React, Next.js, and Node patterns each have their own footguns; a tool blind to them under- and over-reports.
The real tools in 2026
ESLint is the near-universal linter, extensible through plugins; eslint-plugin-security and eslint-plugin-no-unsanitized add a layer of security-flavored rules. Tradeoff: those rules are heuristic and single-file, so they raise awareness but are not a substitute for taint-aware SAST. Biome is the fast Rust-based linter/formatter gaining ground for its speed and zero-config appeal; its rule coverage is narrower than ESLint's mature ecosystem.
The TypeScript compiler itself, run in strict mode, is a correctness tool you already own. Use it.
Semgrep has strong JavaScript and TypeScript support with readable custom rules and cross-file taint — good for encoding the insecure patterns your team keeps hitting. CodeQL provides the deepest free semantic analysis for JS/TS and integrates with GitHub code scanning; private repos need GHAS. SonarQube / SonarCloud brings quality gates and security hotspots with good reporting but less taint depth than specialists. Snyk Code offers AI-assisted SAST with a smooth developer experience; depth on the hardest cases is more limited (see Safeguard vs Snyk). NodeJsScan is a focused free option for Node-specific patterns.
For dependencies, npm audit is the built-in baseline (noisy, no reachability), and Socket analyzes package behavior in real time to catch malicious and suspicious packages before they land.
| Tool | Category | Strength | Watch-out |
|---|---|---|---|
| ESLint | Lint + light security | Ubiquitous, extensible | Heuristic, single-file |
| Biome | Lint/format | Very fast, zero-config | Narrower rule set |
| TypeScript (strict) | Type checking | Eliminates bug classes | Not vuln detection |
| Semgrep | Security SAST | Custom rules, taint | Deep rules paid |
| CodeQL | Security SAST | Deepest free analysis | GHAS for private |
| SonarQube | Quality + security | Gates, reporting | Less taint depth |
| npm audit / Socket | SCA / supply chain | Built-in / behavior analysis | audit is noisy |
How these fit with SCA and reachability
The defining fact of JavaScript security is the dependency tree. A modest Next.js app can install more third-party code than it contains first-party code by an order of magnitude, and npm is where supply-chain attackers concentrate — typosquats, hijacked maintainer accounts, and install-time scripts. So SAST on your source is necessary but covers a small fraction of what actually ships. SCA covers the rest.
The problem with plain npm audit-style SCA is that it reports every advisory in every transitive package, and most of those code paths never execute in your app. Reachability analysis fixes the signal problem: it walks the call graph to determine whether your code actually reaches the vulnerable export, so a wall of advisories collapses to the handful you can truly trigger. Applied to SAST findings, the same technique surfaces issues on live routes first. That is how you keep a fast, developer-friendly loop without drowning in noise. See how reachability-aware SCA works.
Where Safeguard fits
Keep ESLint, Biome, and strict TypeScript in the inner loop — they are fast and they belong there. Safeguard sits one layer out, joining SAST on your JS/TS with reachability-aware SCA on the npm graph so you get a single prioritized queue instead of a lint report next to an unreadable npm audit dump. It runs reachability across your code and dependencies to focus on exploitable paths, and it draws on a curated catalog of 500K+ zero-CVE components to swap out risky packages at the source. Griffin AI performs autonomous remediation, verified by a model-agnostic step before anything opens as a pull request, and Auto-Fix handles the mechanical upgrades. Because AI assistants write so much JavaScript now — and confidently suggest packages that sometimes do not exist — the provenance and prioritization layers matter more than another findings list. The $1 Starter plan lets you try it on one real repo; it runs cloud, on-prem, and air-gapped.
Safeguard does not replace a dedicated behavior analyzer like Socket for the malicious-package problem; it unifies the code-plus-dependency view and closes the loop to a verified fix.
Frequently Asked Questions
Does ESLint find security vulnerabilities?
Only lightly. With plugins like eslint-plugin-security, ESLint flags some risky patterns, but those rules are heuristic and single-file. They raise awareness rather than provide real coverage. Use a taint-aware SAST tool such as Semgrep or CodeQL alongside ESLint for actual vulnerability detection.
Is npm audit enough for dependency security?
No. It reports known advisories but with heavy noise and no reachability, so most of what it flags is code your app never executes. It also misses behavioral threats like malicious install scripts. Pair it with reachability-aware SCA and a behavior analyzer for real coverage.
Should I use Biome or ESLint? Biome is dramatically faster and pleasant to configure, but ESLint has a far larger plugin ecosystem, including the security-oriented rules. Many teams run Biome for formatting and fast lints while keeping ESLint for the rules Biome does not yet cover. Neither is a security scanner.
How does AI-generated JavaScript change things? Assistants generate large volumes of JS/TS and often suggest npm packages, occasionally ones that are typosquats or do not exist. The scanning categories are unchanged, but volume and dependency provenance matter far more, which raises the value of reachability-based prioritization and verified automated fixes.
Ready to prioritize the JavaScript findings that matter? Create a free account or read the guides in the Safeguard documentation.