PAS7 Studio

SQL Injection Without Myths: How to Find and Fix It in a Project

A practical SQL injection guide: how the attack works, where to find it in code, which language and framework patterns create risk, how to test a project, and which tools and libraries help prevent it.

01 Aug 2026· 10 min read· Technology
Best forBackend engineersFull-stack teamsTech leadsQA engineersProduct owners
Dark illustration of SQL injection where red fragments stop at a blue boundary before a database

Imagine a product search. The application wants to run SELECT * FROM products WHERE name = ?. With a parameter, the database receives the query template and the value separately. When a developer manually concatenates a string, input can change the WHERE structure, add another condition, or terminate the command.

SQLi is an interpretation flaw: trusted code and untrusted data were mixed in one string. [1]
Impact depends on the database account's permissions: from one leaked record to reading, changing, or deleting large amounts of data.
The fix starts with parameterization but also needs least privilege, logging, and regression tests. [1]
Test your own staging environment or a lab such as PortSwigger Academy; never test third-party systems without written permission. [5]
01

The user controls a value

It may be a query string, JSON body, cookie, header, CSV import, webhook, sort parameter, or queue message. If an external party can change its source, treat it as untrusted.

02

The value is joined to SQL

The risk appears in query = '... ' + input + ' ...', a template string, a raw query builder, or an ORM method that accepts finished SQL. Format validation does not replace parameterization.

03

The database sees syntax, not data

Special characters and SQL fragments may change a condition, combine results, affect response timing, or turn a read into a write operation, depending on the driver and permissions.

04

The flaw reaches beyond one endpoint

If a connection user has excessive permissions, one compromised endpoint can expose tables, reports, personal data, backups, or another tenant's records.

Mental model

Do not ask only whether the project uses an ORM. Ask whether external input can affect SQL structure and which privileges execute the query.

Read these numbers carefully. OWASP measures the broad Injection category, which includes SQLi, XSS, and other CWEs. MITRE scores CWE-89 from CVE data. This is not a percentage of all attacks and not a ranking of programming languages.

274,228

total occurrences for the Injection category in the OWASP dataset; average incidence rate was 3.37%. [2]

#2

SQL Injection ranked second in MITRE's 2025 CWE Top 25, with a score of 28.72. [3]

94%

of applications in the study were tested for some form of injection. [2]

What this means for a team

SQLi is a mature, well-described problem, but maturity does not make legacy code safe. Its repeatable patterns are useful for defense: they can be checked with static analysis and tests.

Start with the data flow, not a framework list: identify the external source, follow it into the data-access layer, and inspect the actual driver call.

Find dangerous sinks

Search for query, execute, raw, text, literal, sequelize.query, knex.raw, jdbc.Statement, SqlCommand, and equivalents. Check whether they receive a concatenated string.

Review dynamic SQL

Pay special attention to ORDER BY, column/table names, report builders, and filters. Bind variables often cannot represent identifiers; use an allow-list mapping from fixed values instead. [1]

Inspect ORM escape hatches

Review raw SQL, unsafe operators, custom scopes, string filters, and migrations. An ORM lowers risk only when the team stays on its parameterized APIs.

Include non-obvious entry points

Admin panels, imports, cron jobs, integrations, GraphQL resolvers, search endpoints, and internal APIs also process data that may have been compromised earlier in the chain.

Check error handling

SQL stack traces, table names, driver details, or different errors for different conditions make attacks easier to diagnose. Return a safe public error and keep details in correlation-ID logs.

There is no honest ranking of the most dangerous language: SQLi is possible anywhere SQL meets an unsafe API. The difference is how easy it is to accidentally leave the parameterized path for raw SQL.

EcosystemTypical risk pointSafer defaultWhat to review
PHP: Laravel / SymfonyDB::raw, query strings, old mysqli/PDO codeQuery Builder/Eloquent bindings, PDO prepared statementsraw(), bound parameters, legacy controllers
JavaScript / TypeScript: Node.jspg/mysql2 template strings, knex.raw, Sequelize rawdriver placeholders, Prisma parameters, query builders$queryRawUnsafe, raw(), dynamic filters
Python: Django / SQLAlchemycursor.execute concatenation, text() with a stringDjango QuerySet, SQLAlchemy bound parametersextra(), raw(), literal SQL, f-strings
Java: Spring / HibernateStatement, string concatenation, HQL interpolationPreparedStatement, JPA parameters, named parameterscreateNativeQuery, HQL interpolation
.NET: ASP.NET / EF CoreFromSqlRaw or SqlCommand with a stringLINQ, FromSqlInterpolated, parametersraw methods, interpolated SQL, database role
Go / Rustdatabase/sql or client APIs with string buildingQueryContext/Execute placeholders, sqlx bindfmt.Sprintf, format!, dynamic identifiers

The stack-level conclusion

The largest risk comes not from a language, but from teams that mix input with query text, allow raw SQL without review, or give the application a DBA role.

Unsafe: the string knows too much

TS
const sql = `SELECT * FROM users WHERE email = '${email}'`;
const result = await db.query(sql);

Here email becomes part of the SQL text. Even if this starts as a search, the pattern is easily copied into login, export, or admin features.

Safer: the driver separates values

TS
const result = await db.query(
  "SELECT * FROM users WHERE email = $1",
  [email],
);

The query text is fixed and email is passed as a value. Placeholder syntax differs between drivers, so follow your client library's documentation.

For sort fields, use a mapping

TS
const columns = { newest: "created_at", price: "price" } as const;
const column = columns[input] ?? columns.newest;
const sql = `SELECT * FROM products ORDER BY ${column}`;

Column names are not ordinary bind values. Allow only keys from a fixed list and never insert raw input directly.

No single tool sees the whole picture. The strongest workflow combines code analysis, endpoint testing, and runtime observation.

CodeQL

SAST for tracing data from user input to SQL sinks in JavaScript/TypeScript, Python, Java, C# and other supported languages. Add it to CI and review findings with the code owner.

Semgrep

Fast pattern and data-flow rules for local checks and pre-commit. Use it to ban specific unsafe calls such as raw queries without parameters.

Burp Suite / OWASP ZAP

DAST for staging: proxying, request replay, and active or passive scanning. Use an approved scope and never enable destructive checks against production.

PortSwigger Web Security Academy

A safe training environment with SQLi labs covering error-based, blind, UNION, and other scenarios. It lets a team practice without touching customer data.

Sentry / DB audit logs / WAF

Look for unusual 4xx/5xx spikes, latency, SQL parser errors, mass SELECTs, odd user agents, and access to unusual tables. A WAF is a risk-reduction layer, not a code patch.

OWASP recommends more than one filter. Build a defense-in-depth baseline and make it part of the Definition of Done.

Use parameterized queries or safe stored procedures; dynamic SQL needs an allow-list and a separate review. [1]

Do not rely on escaping as the primary defense: OWASP calls it fragile and recommends it only as a last resort for legacy code. [1]

Use a dedicated application database user with minimum SELECT/INSERT/UPDATE permissions, never a DBA/owner role. Use read-only accounts or views for read-only flows. [1]

Do not put secrets or production data in logs. Record endpoint, actor, request ID, and policy result, not full SQL with personal parameters.

Add negative tests: quotes in legitimate names, long strings, Unicode, wrong types, unknown sort keys, cross-tenant IDs, and boundary values.

Keep the driver, ORM, and database engine patched, but do not treat dependency updates as a replacement for safe query construction.

First hour

Stop the damage from spreading

Capture the endpoint, time, request ID, and scope. If needed, disable the feature, restrict the route, or reduce the database role to read-only. Do not delete logs or experiment on production.

Same day

Fix the root cause

Replace string-built SQL with a parameterized API, add allow-list mapping for identifiers, review database permissions, and write a regression test that fails against the old implementation.

After the patch

Check the blast radius

Review database audit logs, unusual exports, data changes, service accounts, and access to other tenants. Record what may have been read or changed.

Before closing

Improve the process

Add SAST/DAST to CI, a review rule for raw queries, a least-privilege migration, and a short incident playbook. Otherwise the next SQLi will appear in another endpoint.

Does an ORM prevent SQL injection?

ORMs usually parameterize standard queries, but they do not automatically protect raw SQL, unsafe operators, dynamic identifiers, or custom query builders. Review escape hatches and team rules.

Is checking that a field contains only digits enough?

Format validation helps, but it is not a universal defense. Use parameterized queries for values and fixed allow-list mappings for table names, column names, and sorting.

Can SQLi happen in GraphQL?

Yes. GraphQL changes the API shape, but a resolver can still pass an argument into unsafe SQL, a filter, or a raw query. Trace data flow from resolver arguments to the database client.

Does a WAF solve the problem?

A WAF can block known patterns and reduce exploitation, but it does not fix query construction or guarantee coverage of obfuscation and business-specific paths. Patch, least privilege, and tests remain necessary.

How can a team practice SQLi safely?

Use a local sandbox, OWASP Juice Shop, WebGoat, or PortSwigger Academy. Never test a third-party site, client API, or production system without an explicitly approved scope.

Reviewed: 01 Aug 2026Applies to: Web applicationsApplies to: REST APIsApplies to: GraphQL APIsApplies to: Background jobsApplies to: Admin panelsTested with: OWASP Top 10:2021Tested with: CWE Top 25:2025Tested with: OWASP SQL Injection Prevention Cheat Sheet

PAS7 Studio can review your API, admin panel, and data-access layer: find raw SQL, check tenant boundaries, configure SAST/DAST in CI, reduce database permissions, and prepare a prioritized remediation plan.

Related Articles

ai-assistants

AI Assistant Development Cost in 2026: RAG Chatbots, CRM Integrations, Guardrails, and Support

A practical buyer guide to AI assistant development cost in 2026: prototypes, RAG chatbots, knowledge-base assistants, CRM and website integrations, guardrails, evaluations, monitoring, and support.

blogs

AI-assisted attacks and prompt injection in 2026: the new attack surface for AI products

AI-assisted attacks and prompt injection in 2026: the new attack surface for AI products. A practical PAS7 Studio security guide with threat model, controls, rollout checklist, pitfalls, and sources.

blogs

AI for landing page development: where it speeds up launches and where it hurts conversion

A practical research piece on using AI for landing page development: v0, Webflow AI, Builder.io, Framer-like builders, UX generation, copy, SEO, personalization, A/B testing, template risk, accessibility, security and technical debt.

growth

AI SEO / GEO in 2026: Your Next Customers Aren’t Humans — They’re Agents

Search is shifting from clicks to answers. Bots and AI agents crawl, cite, recommend, and increasingly buy. Learn what AI SEO / GEO means, why classic SEO is no longer enough, and how PAS7 Studio helps brands win visibility in the agentic web.

Professional development for your business

We create modern web solutions and bots for businesses. Learn how we can help you achieve your goals.