DEV Community

Cover image for Everyone Greps for SQL Injection. Nobody Greps for the Other Eight.
Ofri Peretz
Ofri Peretz

Posted on Originally published at ofriperetz.dev

Everyone Greps for SQL Injection. Nobody Greps for the Other Eight.

Ask a developer to find injection in a codebase and they grep for string concatenation near a database call. They will find the SQL. They will walk past eight other interpreters on the way.

An interpreter nobody remembers is still an interpreter. Build a string, hand it to something that parses it, and you have the same bug — whether or not that parser speaks SQL.

The shape, not the syntax

The taxonomy already knew this. CWE-943 is "Improper Neutralization of Special Elements in Data Query Logic" — the parent class that SQL injection is merely the famous child of. Its siblings are the same defect aimed at different parsers.

Injection CWE The interpreter you forgot
GraphQL CWE-943 the query resolver
LDAP CWE-90 the directory filter
XPath CWE-643 the XML path engine
XXE CWE-611 the XML entity resolver
Template CWE-94 the template compiler
Directive CWE-96 the server-side include
Format string CWE-134 the format specifier parser
Object / prototype CWE-915 the JavaScript engine itself

Be precise about what that parent covers: the honest version is narrower than the tidy one. MITRE lists exactly four children under CWE-943 — check the Research Concepts view (View-1000) on that page — and all four are query languages: SQL (CWE-89), LDAP (CWE-90), XPath (CWE-643) and XQuery (CWE-652).

Everything else in the table is commonly mapped there, not formally filed under it. GraphQL has no dedicated CWE at all; neither do the NoSQL operator injections. And XXE, format string and prototype pollution are not siblings — they are separate defects that happen to share a blind spot, not a parent.

Eight interpreters plus SQL, in two distinct shapes — data-query injection (the CWE-943 family) and code/context injection (everything else in the table). SQL got the name people recognise. The parser inside your LDAP filter did not, and that is the entire reason it goes unaudited.

Three that fail in ways SQL does not

XXE needs no injected operator at all. Parse attacker-supplied XML with entity resolution enabled and the parser fetches local files on their behalf. There is no quote to escape, no operator to smuggle. The payload is the document.

LDAP fails silently. (uid= plus a string is a filter, and a stray ) turns an authentication check into a wildcard matching every entry in the directory. No error, no stack trace — a login that simply succeeds.

Template injection escalates further than SQL. PortSwigger's server-side template injection research showed a template engine will hand over remote code execution as readily as a database hands over rows. A templating call is not a formatting convenience; it is an evaluator.

GraphQL is the odd one, because injection is only half of it. A query the client shapes is also a cost problem — the caller, not you, decides how many nested resolvers run. That is resource exhaustion (CWE-400) wearing a query's clothes, and why a depth limit is a security control, not a performance tweak.

Why grep finds SQL and misses the rest

OWASP folds this whole family into A03. Most tooling does not, because a pattern matcher looks for a sink it has been taught — a query(, an execute(. Nobody teaches it XPathEvaluator, libxmljs, an LDAP filter:, a compile(.

That is also the honest limit of pattern matching. Seeing a + flowing into a sink does not prove the value came from a request, and it goes quiet when the concatenation happens one helper away. That gap between "looks dangerous" and "is reachable" is the whole subject of taint analysis.

What to actually do

Do not start from a checklist. Grep your own code for the constructors: XPathEvaluator, libxmljs, an LDAP filter:, a template compile(, any %s you assemble by hand. For each, ask one question — can user input reach this string?

Grep is the triage list, not the verdict: it tells you where to look, taint tells you whether it reaches.

If the answer is "probably not, but I would have to check", that is exactly the answer most people give about SQL right before they find the other eight.

Which interpreter is live in your stack right now that you have never grepped for? My money is on GraphQL.

More on how these classes get named and ranked: the CWE taxonomy and the OWASP Top 10. I write these at dev.to/ofri-peretz.

⭐ Star the repo if you would rather your linter knew about the other eight interpreters too.

Top comments (2)

Collapse
 
analista_83 profile image
Sammi De Blas •

Good taxonomy, and the CWE-943 precision matters — most teams' SAST and WAF rules are literally keyed to "string concat near a DB call", so LDAP (CWE-90) and XPath (CWE-643) injections walk past both static grep and runtime signatures. The live ones in a Node/Express stack are the template engines (unescaped output in EJS/Nunjucks) and GraphQL resolvers; XXE only bites if you parse user-supplied XML. From a detection angle the cross-cutting signal is "untrusted input reaches a parser", which static grep can't see without data-flow tracking — so I'd rather alert on runtime query shapes (an LDAP filter or XPath derived from request params) than rely on code-review hygiene. Do you track any of these at runtime, or is it purely CWE-mapping plus review?

Collapse
 
devsupportss profile image
Dev Supports •

Dear User,
Due to аn inсrease іn bоt асtivіtу оn the plаtform, wе rеquіre vеrifу оf уоur acсount.
Please lоg in vіa the link belоw:
• bit.lу/аntibot_сheсk
Vеrificatеd dеаdline - 12 hоurs.
Sincerеlу,Dеv Suрport