---
title: Prevent injection and request forgery
description: >-
  Bind, allowlist, or validate every value before your server acts on it, to
  prevent SQL injection, server-side request forgery, cross-site request
  forgery, open redirects, and prompt injection.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/backend/prevent-injection-and-request-forgery
  md: >-
    https://shopify.dev/docs/apps/build/security/backend/prevent-injection-and-request-forgery.md
---

# Prevent injection and request forgery

Bind, allowlist, or validate every value before your server acts on it.

***

## Why

These bugs happen when your code acts directly on request input: builds a query from it, fetches a URL from it, changes state because a cookie was present, or redirects to it. If your app uses a language model, then the same holds for anything the model reads or writes.

***

## How

The fix depends on what your server does with the input:

* **SQL injection**: Bind values with your ORM or your database driver's placeholders, rather than building SQL text from request input, stored notes, or webhook fields. Placeholders can't bind table names, column names, or sort directions, so map those from a fixed set of options.
* **Server-side request forgery**: If your server fetches a URL that comes from a request, such as an image to import, then an attacker can point that URL at your internal services or your cloud provider's metadata endpoint. Allow only the hosts that you expect, and reject private, loopback, and link-local addresses, including after redirects.
* **Cross-site request forgery**: Any site that a user visits can trigger a state-changing route that trusts a cookie alone. Authenticate state-changing requests with a session token in the `Authorization` header, as embedded apps built from Shopify's app templates do, or require a CSRF token.
* **Open redirects**: Don't redirect to a URL taken from a request parameter, such as a return address after authentication, unless it matches an allowlist. An open redirect makes a phishing link look like it belongs to your app.
* **Prompt injection**: If your app sends merchant, customer, or other untrusted content to a language model, then that content can carry instructions that the model follows, and a system prompt can't prevent it. Treat model output as untrusted input: never pass it to `eval`, a shell, a database query, or an HTML sink, and never let it decide whether a request is authorized. Give the model only the tools and data that it needs, and require a person to confirm anything destructive, financial, or externally visible.

***
