---
title: Cross-site request forgery protection may be missing
description: >-
  Investigates state-changing endpoints for missing request authenticity
  protections.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/csrf-missing-protection
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/csrf-missing-protection.md
---

# Cross-site request forgery protection may be missing

Investigates state-changing endpoints for missing request authenticity protections.

| Detail | Value |
| - | - |
| Check ID | `CSRF_MISSING_PROTECTION` |
| Severity | Medium |
| How it runs | Agent review |

***

## Vulnerable example

## app/routes/api.discount.apply.tsx

```tsx
import type { ActionFunctionArgs } from "react-router";


import prisma from "../db.server";


// A state-changing endpoint with no session-token check: any
// site the merchant visits can POST here from their browser and
// it will succeed.
export const action = async ({ request }: ActionFunctionArgs) => {
  const formData = await request.formData();


  await prisma.discount.update({
    where: { id: String(formData.get("id")) },
    data: { active: true },
  });


  return { ok: true };
};
```

***

## How to fix

Require an authenticated session and CSRF protection on state-changing requests.

## app/routes/api.discount.apply.tsx

```tsx
import type { ActionFunctionArgs } from "react-router";


import { authenticate } from "../shopify.server";
import prisma from "../db.server";


export const action = async ({ request }: ActionFunctionArgs) => {
  // The embedded app sends a session token on every request.
  // Validating it is what proves the request came from your own
  // admin UI, not a forged form.
  const { session } = await authenticate.admin(request);


  const formData = await request.formData();


  await prisma.discount.updateMany({
    where: { id: String(formData.get("id")), shop: session.shop },
    data: { active: true },
  });


  return { ok: true };
};
```

***

## 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)

***
