# DOM XSS via Shopify.API.remoteRedirect

Shopify admin embedded app postMessage handler failed to verify origin, letting a malicious theme page inject javascript: via Shopify.API.remoteRedirect to XSS the admin.

- Payout: hidden
- Severity: low
- Program: Shopify
- Found by: yxw21
- Disclosed: 2019-06-05
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/576532
- Library page: https://bugbountylibrary.com/r/h1%3A576532
- Tags: area:web domain:web impact:ato impact:privesc kind:bounty platform:hackerone sev:low technique:incomplete-fix technique:source-review vuln:xss

**Target:** Shopify admin embedded app postMessage handler (embeddedApp JS bundle)
**Root cause:** The embedded app's message listener handled `Shopify.API.remoteRedirect` and passed `data.location` to `handleRemoteRedirect` without validating the message origin, so any window could supply a `javascript:` URL.
**Steps:**
1. Craft a theme page containing a script that calls `window.open('https://cuxuri.myshopify.com/admin/themes')` and repeatedly `ctx.postMessage('{"message":"Shopify.API.remoteRedirect","data":{"location":"javascript:alert(document.domain)"}}')` on a 500ms interval.
2. Victim admin logs in and visits the attacker-controlled page, clicking the trigger link.
3. The opened admin window receives the postMessage and `handleRemoteRedirect` navigates to the `javascript:` payload, executing in the admin origin.
**How found:** Read prior report #422043 about a postMessage handler and searched for another listener that also lacked origin verification, finding the RemoteRedirect case in the embeddedApp bundle.
**Exploitation:** Attacker with theme-write access plants a page; a logged-in admin visiting it opens the admin themes URL and the interval-spammed postMessage delivers a javascript: location that executes in the admin context, yielding script execution as the administrator.
**Insight:** When one postMessage handler is reported, grep the same bundle for sibling message-type switch cases (e.g. RemoteRedirect) that reuse the same unvalidated event listener; a single origin check often guards only one branch.

