• Agents
  • Pricing
  • Blog
Log in
Get started

Security for apps built with AI. Paste a URL, get a report, fix what matters.

Product

  • How it works
  • What we find
  • Pricing
  • Agents
  • MCP Server
  • CLI
  • GitHub Action

Resources

  • Guides
  • Blog
  • Docs
  • OWASP Top 10
  • Glossary
  • FAQ

Security

  • Supabase Security
  • Next.js Security
  • Lovable Security
  • Cursor Security
  • Bolt Security

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • Imprint
© 2026 Flowpatrol. All rights reserved.
Home/OWASP Top 10/Web Top 10/A03: Injection
A03CWE-79CWE-89CWE-94

Quote in the input box
Injection

The bug where user input gets pasted directly into a query, a command, or a template.

Affects roughly 3.37% of tested apps.

Reference: Web Top 10 (2021) — A03·Last updated April 7, 2026·By Flowpatrol Team
Injection illustration

Everyone knows about SQL injection. Nobody writes it on purpose anymore. So how does it keep shipping? Because the model wrote a perfectly normal-looking search endpoint, and somewhere in the middle of that endpoint there is a template string that should have been a parameter.

Injection happens when user input gets treated as code instead of data. SQL injection is the famous one, but the family is larger: XSS in the browser, template injection in server-rendered views, command injection in a shell call, NoSQL injection in a Mongo filter. They all share a single root cause — data and instructions sharing the same channel.

What your AI actually built

You asked for a search endpoint. The model gave you one: take a query string, filter the users table, return the matches. Works on the happy path. Looks like every tutorial you have ever read.

What it did not do was bind the parameter. The search term gets concatenated into the SQL directly, because string interpolation reads naturally and the model has seen a thousand examples that look identical. The ORM call right next to it uses prepared statements — but this one raw query slipped through.

The same pattern lives one layer up in the frontend, where a comment renders through dangerouslySetInnerHTML. And one layer down in a job runner that passes a filename into exec without quoting. Different syntax, same bug: data treated as code.

How it gets exploited

The attacker finds a search box on the public site. They type a single quote and press enter.

  1. 1
    Probe the input
    A stray quote crashes the endpoint with a Postgres error message. The error leaks the query, which tells them exactly what to inject.
  2. 2
    Read the schema
    A UNION SELECT against information_schema dumps every table and column name. They find users, sessions, and api_keys.
  3. 3
    Exfiltrate
    A second UNION returns email and password_hash pairs. They page through the results 50 rows at a time.
  4. 4
    Escalate
    The api_keys table includes a Stripe live key. That key works. They are now pulling customer data from an unrelated service.

A single-character payload turned a read-only search box into a full database dump and a pivot into a payments provider. The web server logs show five innocuous GETs.

Vulnerable vs Fixed

Vulnerable — query built by string concat
// app/api/search/route.ts
import { sql } from '@/lib/db';

export async function GET(req: Request) {
  const q = new URL(req.url).searchParams.get('q') ?? '';

  const rows = await sql.unsafe(
    "SELECT id, name FROM users WHERE name ILIKE '%" + q + "%'",
  );

  return Response.json(rows);
}
Fixed — parameterised query
// app/api/search/route.ts
import { sql } from '@/lib/db';

export async function GET(req: Request) {
  const q = new URL(req.url).searchParams.get('q') ?? '';

  const rows = await sql`
    SELECT id, name FROM users
    WHERE name ILIKE ${'%' + q + '%'}
  `;

  return Response.json(rows);
}

The tagged template hands the parameter to the driver separately from the query text. The database now treats q as a value, never as SQL. Nothing else about the endpoint changes.

A real case

British Airways lost 380,000 card records to an injected script

Magecart attackers injected 22 lines of JavaScript into a third-party library on the BA checkout page — the same class of bug, moved to the client side.

Related reading

Glossary

SQLi (SQL Injection)Cross-Site Scripting (XSS)GraphQL Attack Surface (GraphQL Security)

What we find

injection vulnerabilities

References

  • A03: Injection — official OWASP entry
  • OWASP Top 10 for Web Applications (2021) — full list
  • CWE-79 on cwe.mitre.org
  • CWE-89 on cwe.mitre.org
  • CWE-94 on cwe.mitre.org

Find every place user input ends up in a query.

Flowpatrol probes every route on your app and confirms each injection finding with a real payload. Five minutes. One URL.

Try it free