---
title: Query scoped by shop value taken from request input
description: >-
  Detects queries whose shop scope comes from request params rather than the
  authenticated session. Presence of a shop key is not proof of scoping when its
  value is attacker-controlled.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/request-derived-shop-scope
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/request-derived-shop-scope.md
---

# Query scoped by shop value taken from request input

Detects queries whose shop scope comes from request params rather than the authenticated session. Presence of a shop key is not proof of scoping when its value is attacker-controlled.

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

***

## Vulnerable example

## app/routes/app.settings.tsx

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


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


export const loader = async ({ request }: LoaderFunctionArgs) => {
  await authenticate.admin(request);


  const shop = new URL(request.url).searchParams.get("shop");


  // There is a shop filter, but its value is attacker-controlled,
  // so it scopes the query to whichever shop the caller names.
  return {
    settings: await prisma.appSetting.findMany({ where: { shop } }),
  };
};
```

***

## How to fix

Scope the query with the shop from the authenticated session, or verify the supplied shop against a signed session or HMAC first.

For more detail, see [Session tokens](https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens).

## app/routes/app.settings.tsx

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


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


export const loader = async ({ request }: LoaderFunctionArgs) => {
  const { session } = await authenticate.admin(request);


  // Scope from the session. If a shop must arrive in the request,
  // compare it to session.shop and reject a mismatch before
  // querying.
  return {
    settings: await prisma.appSetting.findMany({
      where: { shop: session.shop },
    }),
  };
};
```

***

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

***
