---
title: Cross-site scripting risk
description: >-
  Investigates lower-trust data rendered as executable browser content in
  app-owned pages.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/cross-site-scripting
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/cross-site-scripting.md
---

# Cross-site scripting risk

Investigates lower-trust data rendered as executable browser content in app-owned pages.

| Detail | Value |
| - | - |
| Check ID | `CROSS_SITE_SCRIPTING` |
| Severity | High |
| How it runs | Agent review |

***

## How to fix

Escape, serialize, validate, or sanitize each untrusted value for the context where it's output.

For more detail, see [OWASP Cross Site Scripting Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).

**Don’t**

* Render product titles, metafields, customer input, or any other data you don't control as raw HTML.
* Rely on HTML escaping when a value goes into an event handler attribute, a URL, or a `<script>` block. Each of those contexts needs its own encoding.
* Put a user-supplied URL in an `href` or `src` without checking its scheme. A `javascript:` URL runs code when it's clicked or loaded.

**Do**

* Escape or serialize each value where it's output, for the context it lands in: HTML text, attribute, URL, or script.
* Keep your framework's autoescaping on. When you need to allow some HTML, sanitize it with an allowlist, such as DOMPurify, and allow only the tags you need.
* Validate URLs against the schemes and hosts you expect before you render them as links or sources.

***

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

***
