---
title: App proxy request trusted without signature verification
description: Detects app proxy parameters read without visible signature verification.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/app-proxy-unverified-signature
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/app-proxy-unverified-signature.md
---

# App proxy request trusted without signature verification

Detects app proxy parameters read without visible signature verification.

| Detail | Value |
| - | - |
| Check ID | `APP_PROXY_UNVERIFIED_SIGNATURE` |
| Severity | High |
| How it runs | Agent review |
| Applies to | Apps with an app proxy |

***

## Vulnerable example

## app/routes/proxy.orders.tsx

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


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


export const loader = async ({ request }: LoaderFunctionArgs) => {
  const url = new URL(request.url);


  // Proxy parameters are only trustworthy once the HMAC is
  // checked. Unverified, anyone can call the endpoint with any
  // shop or customer id.
  return {
    orders: await prisma.order.findMany({
      where: {
        shop: url.searchParams.get("shop") ?? undefined,
        customerId:
          url.searchParams.get("logged_in_customer_id") ?? undefined,
      },
    }),
  };
};
```

***

## How to fix

Verify app proxy signatures before trusting shop, customer, or path parameters.

For more detail, see [Authenticate app proxies](https://shopify.dev/docs/apps/build/online-store/app-proxies/authenticate-app-proxies).

## app/routes/proxy.orders.tsx

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


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


export const loader = async ({ request }: LoaderFunctionArgs) => {
  // Verifies the proxy signature and returns the shop it was
  // signed for.
  const { session } = await authenticate.public.appProxy(request);


  if (!session) throw new Response("Unauthorized", { status: 401 });


  // Verification proves the request came from Shopify, not that a
  // customer is signed in: logged_in_customer_id is empty for a
  // guest. The signature covers the query string, so once
  // verification passes this value is trustworthy.
  const url = new URL(request.url);
  const customerId = url.searchParams.get("logged_in_customer_id");


  if (!customerId) throw new Response("Unauthorized", { status: 401 });


  return {
    orders: await prisma.order.findMany({
      where: { shop: session.shop, customerId },
      select: { id: true, name: true, fulfillmentStatus: 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)

***
