App proxy Liquid injection risk
Detects app proxy endpoints that interpolate request parameters into active Liquid or HTML responses.
| Detail | Value |
|---|---|
| Check ID | APP_PROXY_LIQUID_INJECTION |
| Severity | High |
| How it runs | Deterministic scan and agent review |
Anchor to Vulnerable exampleVulnerable example
app/routes/proxy.welcome.tsx
import type { LoaderFunctionArgs } from "react-router";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const shop = new URL(request.url).searchParams.get("shop");
// Request input interpolated into a Liquid response. The
// storefront renders the body as Liquid, so injected tags
// such as {{ customer.email }} run too.
return new Response(`<div>Welcome, ${shop}</div>`, {
headers: { "Content-Type": "application/liquid" },
});
};
Anchor to How to fixHow to fix
Don't interpolate user input into application/liquid responses. Use application/json or escape all input.
For more detail, see App proxies.
app/routes/proxy.welcome.tsx
import type { LoaderFunctionArgs } from "react-router";
import { authenticate } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
// The verified session carries the shop, and JSON is not an
// active content type, so nothing in the body is evaluated.
const { session } = await authenticate.public.appProxy(request);
return new Response(JSON.stringify({ shop: session?.shop }), {
headers: { "Content-Type": "application/json" },
});
};
shopify app security check, the command that runs this check- All app security checks
Was this page helpful?