# Preview bar: Incomplete message origin validation results in XSS

Preview bar's origin check used indexOf without trailing slash, so attacker domain like roolee.co passed validation and injected javascript: redirect XSS into shop front.

- Payout: hidden
- Severity: medium
- Program: Shopify
- Found by: palant
- Disclosed: 2018-07-26
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/381192
- Library page: https://bugbountylibrary.com/r/h1%3A381192
- Tags: area:web domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:medium technique:chained technique:source-review vuln:open-redirect vuln:xss

**Target:** storefront preview_bar_injector JS message listener
**Root cause:** Origin validation used `this.iframeSrc.indexOf(event.origin) < 0` without requiring a trailing slash, so a prefix-matching origin (e.g. https://foo.my vs https://foo.myshopify.com) was accepted.
**Steps:**
1. Load preview_bar_injector JS which registers a `message` listener checking `this.iframeSrc.indexOf(event.origin) < 0`.
2. Register/own a domain that is a string prefix of the shop's iframeSrc origin, e.g. `roolee.co` for `roolee.com` (or `foo.my` for `foo.myshopify.com`).
3. Host a page on that origin that opens the shop with `?preview_theme_id=<id>` in a frame and postMessage an `exit_preview` message with a `javascript:` redirect URL.
4. Origin check passes; the javascript: URL executes in the shop front context.
**How found:** Reading the preview bar injector source, noticing the origin check used indexOf without a trailing slash, and reasoning that event.origin lacks a trailing slash so a prefix domain would be accepted.
**Exploitation:** Attacker page on prefix-matching origin frames the victim shop with a valid preview_theme_id, sends exit_preview with javascript: URL, achieving script execution in shop origin; can then alter prices/shipping for customers or, via hidden frame plus popup to /admin/, abuse admin session to read CSRF tokens/config or change password.
**Escalation:** Chained storefront XSS to admin interface access via same-origin popup to /admin/, enabling account takeover.
**Insight:** When origin checks use substring/prefix matching, look for domains that are string prefixes of the target origin (e.g. `foo.my` vs `foo.myshopify.com`); also check whether sensitive admin panels share the same origin as user-content-rendering surfaces.

