---
title: SQL injection risk
description: >-
  Investigates lower-trust input that changes SQL syntax in a reachable database
  operation.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/sql-injection
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/sql-injection.md
---

# SQL injection risk

Investigates lower-trust input that changes SQL syntax in a reachable database operation.

| Detail | Value |
| - | - |
| Check ID | `SQL_INJECTION` |
| Severity | High |
| How it runs | Agent review |

***

## How to fix

Bind query values and use trusted mappings or safe identifier quoting for dynamic SQL structure.

For more detail, see [OWASP SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html).

**Don’t**

* Concatenate or interpolate request input, stored notes, or webhook fields into SQL text.
* Build the query string for a raw-query API, such as Prisma's `$queryRawUnsafe` or `$executeRawUnsafe`, from request input.
* Take table names, column names, or sort directions straight from a request. Placeholders can bind values, but they can't bind identifiers or keywords.

**Do**

* Bind values through your ORM's query builder or the driver's placeholders. Prisma's `$queryRaw` tagged template binds every interpolated value.
* Map table names, columns, and sort directions from user input to a fixed set of SQL fragments.
* Keep SQL structure separate from data, including `IN` lists, `LIKE` patterns, and `ORDER BY`.

***

## Related

* [`shopify app security check`](https://shopify.dev/docs/api/shopify-cli/app/app-security-check), the command that runs this check
* [All app security checks](https://shopify.dev/docs/apps/build/security/app-security-checks)

***
