# Admin bar: Incomplete message origin validation results in XSS

Admin bar postMessage origin check used substring match, so attacker domain foo.myshopify.co passed and injected javascript: redirect into shop admin's storefront.

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

**Target:** admin_bar_injector.js postMessage listener on storefront
**Root cause:** Origin validation used this.iframe.src.indexOf(e.origin) < 0, a substring match rather than a prefix match, so an origin like https://foo.my matched the iframe src https://foo.myshopify.com/admin/bar.
**Steps:**
1. Load https://foo.myshopify.co/exploit_admin_bar.html from an attacker-controlled origin whose hostname is a prefix of the victim shop hostname.
2. Page sends a postMessage with action `redirect_to_url` and a `javascript:` URL to the admin bar iframe.
3. Listener accepts because `this.iframe.src.indexOf(e.origin) >= 0` matches the prefix.
4. Handler navigates to the javascript: URL, executing script in the shop front context (blocked only by popup blocker).
**How found:** Noticed the origin check used indexOf on the iframe src rather than a strict prefix/suffix comparison; realized e.origin lacks a trailing slash so a shorter lookalike hostname is a substring of the real src. Same logic as a prior report (381192) in a different script.
**Exploitation:** Attacker lures a logged-in shop admin to a malicious page on a lookalike domain (e.g. foo.myshopify.co or foo.my). The page posts a redirect_to_url message with a javascript: payload to the admin bar iframe; the flawed origin check accepts it and the script runs in the storefront, then opens /admin/ in a popup to read CSRF tokens/config or change the admin password.
**Escalation:** Injected script opens the admin panel in a popup and abuses the active admin session to exfiltrate data or take over the account.
**Insight:** When auditing postMessage origin checks, look for substring/indexOf comparisons instead of exact equality or prefix-with-slash; a domain that is a string prefix of the target host (foo.my vs foo.myshopify.com) passes. Also check whether the handler accepts javascript: URLs.

