Safeguard
Application Security•

How does SAST find SQL injection, and what does it miss?

SAST finds SQL injection by tracing untrusted input to a database call. See how taint analysis works, what it misses and how to fix findings properly.

Safeguard Security Team
4 min read

SAST finds SQL injection by tracing data from places an attacker can control (sources) to places where a query is built and run (sinks). If untrusted input reaches the sink without being handled safely, the tool reports a finding. It can miss flows through frameworks, stored data or unusual code.

What is SQL injection?

MITRE's CWE-89 describes it as building all or part of an SQL command from externally influenced input without neutralizing special elements, so the input can change the command. The effect depends on the database and permissions: reading data, changing it, or in some setups running further commands.

The OWASP prevention guidance gives a clear primary defence: use parameterized queries, where the query text and the values travel separately, so a value can never be read as SQL.

How does SAST detect it?

Most tools use taint analysis, which has three parts.

  1. Sources. Places where outside data enters: request parameters, headers, cookies, uploaded files, message queues.
  2. Sinks. Calls that run SQL, such as a database driver's execute function when passed a string.
  3. Sanitizers. Code the tool trusts to make data safe, such as a parameter binding step.

The tool builds a graph of how values move through assignments, function calls and returns. If it finds a path from a source to a sink with no trusted sanitizer on the way, it reports it, often with the full path so a developer can follow it.

A constructed example

Picture a search handler. It reads a query parameter called name, passes it to a helper called buildFilter, which adds it to a text fragment, and the result is appended to a SELECT statement run in a repository class. Three files are involved. A pattern matcher looking only for string concatenation next to a query call would see nothing wrong in any single file. A taint analyzer follows name across all three and reports one finding with a path.

The fix is to change the repository method to accept the value as a bound parameter. The tool then no longer sees a tainted string reaching the query text, and the finding closes.

What does SAST miss?

  • Framework magic. If an object mapper builds queries from annotations, the tool may not model it and may report nothing or too much.
  • Second order injection. Input is stored safely, then read later and concatenated into a query. The source and sink are far apart in time.
  • Dynamic identifiers. Table or column names chosen by the user cannot be parameterized and need an allow list. Some tools do not flag these.
  • Stored procedures. Unsafe SQL built inside the database is outside the application code.
  • Over-trusted sanitizers. A custom escape function the tool treats as safe may be incomplete.

NIST's SAMATE material is explicit that analyzers vary in what they detect, so treat a clean scan as evidence, not proof.

How do you fix findings the right way?

Escaping by hand is fragile. The OWASP cheat sheet lists defences in order of preference: parameterized queries first, then properly built stored procedures, then allow list validation for values that cannot be bound (such as sort columns), and escaping only as a last resort. It also recommends least privilege for the database account, so a successful injection does less harm.

How to check or apply this

  1. Confirm your tool lists your language's database libraries as sinks. Test with a small deliberately unsafe file in a scratch repository.
  2. Add a rule or review step for any place that builds SQL text from variables.
  3. Make parameterized queries the only approved pattern in your coding guide, with a short example for each language you use.
  4. For dynamic sort or column names, use a fixed mapping from user choice to a known column.
  5. Run the database app account with only the permissions the app needs.
  6. Pair SAST with dynamic testing, which sends requests to a running app and sees real behaviour.
  7. Record each false positive with the reason, so the next reviewer does not repeat the work.

Quick check

Does a clean SAST report mean there is no SQL injection?

No. It means the tool found no path it could model. Second order flows and framework code can hide issues.

Is escaping user input an acceptable fix?

It is a last resort. Parameterized queries are the preferred fix because they separate code from data.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.