---
title: Embedded app frame-ancestors uses a wildcard
description: >-
  Detects literal wildcard or clearly permissive `frame-ancestors` policies in
  embedded app code.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/static-frame-ancestors
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/static-frame-ancestors.md
---

# Embedded app frame-ancestors uses a wildcard

Detects literal wildcard or clearly permissive `frame-ancestors` policies in embedded app code.

| Detail | Value |
| - | - |
| Check ID | `STATIC_FRAME_ANCESTORS` |
| Severity | High |
| How it runs | Deterministic scan and agent review |
| Applies to | Embedded apps |

***

## Vulnerable example

## app/entry.server.tsx

```tsx
export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  reactRouterContext: EntryContext,
) {
  // A hand-written wildcard policy: any origin can frame the
  // embedded app, which is what clickjacking needs. "https:",
  // "*", and "https://*.myshopify.com" all count as permissive.
  responseHeaders.set("Content-Security-Policy", "frame-ancestors *");


  // ... the rest of the template's handleRequest is unchanged.
}
```

***

## How to fix

Restrict `frame-ancestors` to Shopify Admin and the authenticated shop origin.

For more detail, see [Set up iframe protection](https://shopify.dev/docs/apps/build/security/set-up-iframe-protection).

## app/entry.server.tsx

```tsx
import { addDocumentResponseHeaders } from "./shopify.server";


export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  reactRouterContext: EntryContext,
) {
  // Let Shopify build the policy: it restricts frame-ancestors to
  // admin.shopify.com and the shop this request authenticated as.
  // Drop any hand-written wildcard policy elsewhere in the app.
  addDocumentResponseHeaders(request, responseHeaders);


  // ... the rest of the template's handleRequest is unchanged.
}


// Written by hand, the only acceptable shape names both origins
// explicitly, with no wildcard:
//
//   frame-ancestors https://admin.shopify.com https://<shop>.myshopify.com
```

***

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

***
