Skip to main content

Request input selects Admin API shop context

Detects request-derived shop values passed into unauthenticated.admin(...), allowing callers to select another shop's Admin API context.

DetailValue
Check IDREQUEST_CONTROLLED_ADMIN_CONTEXT
SeverityHigh
How it runsDeterministic scan and agent review

app/routes/app.sync.tsx

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

import { authenticate, unauthenticated } from "../shopify.server";

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

const formData = await request.formData();
const requestedShop = String(formData.get("shop"));

// Authenticating and then handing a request value to
// unauthenticated.admin lets the caller pick which shop's Admin
// API context they get.
const { admin } = await unauthenticated.admin(requestedShop);

const response = await admin.graphql(
`{ products(first: 10) { nodes { id } } }`,
);
const { data } = await response.json();

return { products: data.products.nodes };
};

Use the Admin API context returned by authenticate.admin(request). Never pass form, JSON, query, or route input into unauthenticated.admin(...).

For more detail, see Online access tokens.

app/routes/app.sync.tsx

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

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

export const action = async ({ request }: ActionFunctionArgs) => {
// The Admin context comes back bound to the authenticated
// session's shop, so no request value can redirect it.
const { admin } = await authenticate.admin(request);

const response = await admin.graphql(
`{ products(first: 10) { nodes { id } } }`,
);
const { data } = await response.json();

return { products: data.products.nodes };
};


Was this page helpful?