Node.js Security
& Quality Scanning
Node.js has a unique failure-mode profile: SSRF from request-to-fetch data flows, N+1 queries hidden inside async loops, race conditions in concurrent request handlers, resource leaks from unclosed streams, and ReDoS that can halt the event loop. GateTest covers every one.
Node.js-specific modules
ssrferrorTracks req.body/query/params → fetch/axios/got. Flags tainted URLs, metadata endpoints (AWS 169.x.x.x, GCP), suspicious webhook vars without validation.
nPlusOneerrorDatabase calls inside loops across Prisma, Sequelize, TypeORM, Mongoose, Knex, Drizzle, node-pg. Understands Promise.all(arr.map(async...)) as a fix.
raceConditionerrorfs.exists → fs.unlink on the same path. ORM findOne → create without $transaction or ON CONFLICT guard. The get-or-create lost-update bug.
resourceLeakerrorUnclosed streams, file handles, WebSockets, net.createServer. setInterval with discarded return value. Recognises stream.pipeline() as safe cleanup.
redoserrorNested quantifiers (a+)+, overlapping alternation (a|a)*, greedy .* in unanchored patterns. User-controlled RegExp construction (CWE-1333).
retryHygienewarningwhile(true) with fetch and no break/max-attempts (unbounded). Constant sleep with no exponential multiplier (no backoff). No randomised jitter on the sleep. Retry-on-4xx without bail.
tlsSecurityerrorrejectUnauthorized: false in https.Agent. NODE_TLS_REJECT_UNAUTHORIZED=0 (global nuclear disable). strictSSL: false. insecure: true.
cookieSecurityerrorhttpOnly:false (XSS readable), secure:false (rides over HTTP), weak session secret. Express-session, cookie-parser, next/headers.
hardcodedUrlerrorlocalhost / 127.0.0.1 / 0.0.0.0, RFC1918 ranges, .internal/.local/.corp TLDs, staging subdomains in production source code.
sqlMigrationserrorDROP COLUMN/TABLE, ADD COLUMN NOT NULL without default, SET NOT NULL, CREATE/DROP INDEX without CONCURRENTLY, ALTER TYPE rewrites, TRUNCATE.
Why these bugs survive code review
SSRF, N+1, race conditions, and resource leaks are invisible to linters and most static analysis tools. They require understanding what code does, not just how it looks. GateTest uses data-flow analysis and AI reasoning to find bugs that pattern-matching tools miss entirely.
const url = req.query.webhook; fetch(url); // ← SSRF: user controls the target
→ caught by ssrfconst users = await db.user.findMany();
for (const u of users) {
// 1 query per user:
u.orders = await db.order.findMany({where: {userId: u.id}});
}→ caught by nPlusOne// handle never used: setInterval(syncData, 30_000); // nothing calls clearInterval
→ caught by resourceLeakFrequently asked questions
What Node.js security issues does GateTest find?
GateTest covers the full OWASP Top 10 for Node.js: SSRF (tracking user-controlled input from req.body to fetch()), SQL injection patterns, ReDoS (catastrophic regex that can halt your event loop), TLS validation bypass (rejectUnauthorized: false, NODE_TLS_REJECT_UNAUTHORIZED=0), cookie security misconfigs (httpOnly: false, secure: false, weak secrets), hardcoded localhost URLs that leak to production, PII in logs (console.log(user), logger.info(req.body)), and more.
Does GateTest detect N+1 query problems in Node.js ORMs?
Yes. The nPlusOne module covers Prisma, Sequelize, TypeORM, Mongoose, Knex, Drizzle, node-postgres, MySQL2, and generic db/orm/repo shapes. It finds database calls inside loop bodies — for loops, while loops, .map(), .forEach(), .filter(), .reduce(). It recognises await Promise.all(arr.map(async () => await db.query(...))) as the batched fix pattern and records it as info rather than error.
Does GateTest detect resource leaks in Node.js?
Yes. The resourceLeak module catches: unclosed fs.createReadStream / createWriteStream (error), fs.open / fs.promises.open file handles that are never closed (warning), WebSocket / EventSource / net.createConnection objects that are never closed (warning), and setInterval calls where the return value is discarded (error — no way to call clearInterval). It recognises stream.pipeline() and stream.finished() as proper cleanup patterns.
How does GateTest catch SSRF in Node.js apps?
The ssrf module tracks taint from request sources (req.body, req.query, req.params, req.headers) to HTTP client calls (fetch, axios, got, http.request, https.request, needle, superagent, undici, ky). If user input flows to a URL without an intermediate validator (validateUrl(), isValidUrl(), allowedHosts.includes(), new URL(x).hostname check), GateTest flags it as an error. It also flags hardcoded cloud-metadata endpoints (AWS 169.254.169.254, GCP metadata.google.internal).
Does GateTest detect race conditions in Node.js?
Yes. The raceCondition module catches TOCTOU (check-then-act) patterns: fs.exists()/fs.stat()/fs.access() followed within 15 lines by a destructive fs operation (unlink/rm/rename/chmod/copyFile/truncate) on the same path. For databases, it catches Prisma/Sequelize/Mongoose/TypeORM findFirst/findOne followed by create/update/upsert on the same model without a visible $transaction, ON CONFLICT, or upsert guard — the get-or-create lost-update bug.
Does GateTest find ReDoS vulnerabilities in Node.js?
Yes. The redos module extracts regex patterns from literal form (/pattern/), new RegExp('...') constructors, and checks for three catastrophic backtracking shapes: nested quantifiers ((a+)+, (.*)*), alternation with overlapping branches inside quantified groups ((a|a)*), and greedy .* sequences in unanchored patterns. It also catches user-controlled regex construction (new RegExp(req.body.pattern)) — a CWE-1333 injection vector.
Find the bugs that survive code review.
SSRF, N+1, race conditions, resource leaks, ReDoS — GateTest catches every Node.js failure mode. One-time payment per scan.
Scan My Node.js App — From $29One-time payment per scan via Stripe. No subscription, no auto-renew.