The bug is 28 years old and the fix is unchanged. What has changed is the surface area. GraphQL resolvers, JSON path filters, second-order attacks, AI-generated query code, and serverless cold-starts all have the same flaw - a string-concat query where a bound parameter should be.
- L13Finding it in the wild
- L17WAF & detection
- Map modern attack surfaces (GraphQL, JSON, serverless, AI) to the same string-concat bug.
- Recognise a second-order SQLi where the first endpoint is safe.
- Audit AI-generated query code with the same checklist you would use for human-written code.
- Explain why the fix is unchanged even when the surface evolves.
- Second-order SQLi
- A SQLi where the payload is stored by a safe endpoint and read back by a vulnerable one. The first endpoint parameterises; the second concatenates. The bug is in the reader, not the writer.
- GraphQL resolver
- A function that maps a GraphQL field to data. Resolvers that accept user-controlled arguments and pass them into a SQL filter are a common SQLi surface.
- JSON path filter
- An API pattern where the user supplies both a column name and a value (filter[email]=a@b.com). The key is the attack surface, not the value.
- AI-generated query
- A SQL query produced by an LLM. The LLM is trained on a corpus that includes both safe (parameterised) and unsafe (string-concat) patterns. The output requires the same review as a junior developer's first PR.
The same bug, new surfaces
The technology stack evolves. The bug does not. Every modern SQLi surface reduces to a string-concat query somewhere in the request path. The lesson is the same as lesson 1 - keep code and data separate at the database boundary.
GraphQL resolvers often accept arguments that map to SQL filters. A resolver that concatenates the argument into a WHERE clause is a SQLi.
SELECT * FROM users WHERE filter = "${search}"The pattern across five years
The OWASP API Security Top 10 (2019, 2023) has consistently listed "broken object level authorization" and "broken authentication" as the top two findings. SQLi has dropped off the OWASP web top 10 in some recent versions not because the bug is fixed, but because the surface has shifted to API endpoints where the SQL grammar is one or two layers away from the request. The GraphQL resolver, the JSON path filter, the second-order read are all SQLi in production - the OWASP list just looks at the API surface, not the database layer.
AI-generated code is the new wildcard. A 2024 study of LLM-generated SQL found that 35% of generated queries used string interpolation when a parameter was needed. The fix is the same as for a junior developer's first PR: review every generated query with the same checklist you would use for a human author.
The same fix, on every surface
// VULNERABLE - GraphQL resolver
function user(_, { id }) {
return db.query("SELECT * FROM users WHERE id = '" + id + "'");
}
// SAFE - bound parameter
function user(_, { id }) {
return db.query('SELECT * FROM users WHERE id = $1', [id]);
}The fix is the same regardless of whether the surface is REST, GraphQL, JSON, serverless, or LLM-generated. The bug is always a string-concat query. The fix is always a bound parameter.
What to remember
- Modern SQLi surfaces - GraphQL, JSON, serverless, AI - all reduce to a string-concat query.
- Second-order SQLi is a SQLi where the writer is safe and the reader is vulnerable. Audit both.
- Review AI-generated query code with the same checklist as a human PR.
- The fix is unchanged: bound parameter. The surface evolves; the defence does not.
Knowledge check
0/3 answered · 0 correct1.What is a second-order SQLi?
2.Why is AI-generated query code a meaningful SQLi risk?
3.Why is "the fix is unchanged" the right summary of modern SQLi defence?