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 |
Anchor to Vulnerable exampleVulnerable example
app/routes/app.settings.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 } }),
};
};
Anchor to How to fixHow 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.
app/routes/app.settings.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 },
}),
};
};
shopify app security check, the command that runs this check- All app security checks
Was this page helpful?