Ofri Peretz Posted on May 31 • Originally published at ofriperetz.dev Three SQL Injection Patterns That Still Ship in Node.js — And the ESLint Rule That Catches Them # eslint # postgres # security # node TypeScript passed it clean. The code reviewer approved it. It shipped to production. Three months later, a penetration tester sent a report. The vulnerable line: const result = await pool . query ( " SELECT * FROM orders WHERE user_id = " + req . query . userId ); Enter fullscreen mode Exit fullscreen mode SQL injection has been a known problem for decades. OWASP A03:2021. Parameterized queries are widely understood. And it still ships — not because developers don't know, but because the three structural forms that actually appear in node-postgres codebases look harmless in code review, one line at a time. ( CWE-89 ) Here are the three patterns, why each survives review, and how a pg-specific ESLint rule catches them statically. Why a pg-specific rule — not a generic SQL injection linter Most SQL injection detectors work on one signal: string concatenation near a SQL keyword. If they see "SELECT" + variable , they flag it. This produces false positives on non-query string building, and misses injection via template literals — which is syntactically distinct from + but equally dangerous. A pg-specific rule knows three things a generic tool doesn't: The API surface. Only fires on .query() calls — pool.query() , client.query() . Not on other string operations that happen to mention SQL keywords. The parameterization contract. pg uses $1, $2 positional placeholders, with values passed as the second argument array. If the second argument is a non-empty array, the rule treats the first argument as parameterized and stays silent. Note: client.query("SELECT..." + x, []) with an empty array would still be a vulnerability — the rule checks for the presence of a values argument, not that every dynamic part is covered by a placeholder. Cross-line assignment taint. When a S
Back to Home

Three SQL Injection Patterns That Still Ship in Node.js — And the ESLint Rule That Catches Them
B
Blizine Admin
·2 min read·0 views
📰Dev.to — dev.to
B
Blizine Admin
View Profile Staff Writer