# Unauthenticated Stored XSS on <any>.myshopify.com via checkout page

Stored XSS in Shopify checkout first-name field bypassed HTML filter using <html> tag, executing in the thank-you page title on any myshopify.com store.

- Payout: hidden
- Severity: high
- Program: Shopify
- Found by: zombiehelp54
- Disclosed: 2016-12-16
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/189378
- Library page: https://bugbountylibrary.com/r/h1%3A189378
- Tags: area:web domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:high tech:payment technique:source-review vuln:xss

**Target:** checkout.shopify.com order thank-you page <title> tag
**Root cause:** The first-name field's HTML filter rejects most tags but allows the <html> tag itself, and the value is rendered unsanitized inside the <title> tag of the thank-you page.
**Steps:**
1. Create a $0 product with free shipping to avoid payment details.
2. As a user, buy the product and reach checkout.shopify.com details form.
3. Enter `</title></head><html onmouseover=alert(2)>` in the first name field.
4. Complete order via Continue to shipping/payment/Complete order.
5. XSS triggers on checkout.shopify.com; visit `<store>.myshopify.com/<id>/checkouts/<checkout_id>/thank_you` to execute on the store domain.
**How found:** Noticed the checkout form rejected HTML tags with a 'cannot contain HTML tags' error, then tested which tags slipped through and found <html> was allowed; traced where the first name was reflected and found it unsanitized in the thank-you page <title>.
**Exploitation:** Attacker places the payload in the customer first name during checkout; the thank-you page renders it in the <title>, breaking out of the title/head and injecting an <html onmouseover> handler that fires on any myshopify.com store's thank-you URL, enabling CSRF token theft and malicious admin actions.
**Escalation:** Payload executes on <any>.myshopify.com via the thank_you path, extending impact from checkout.shopify.com to arbitrary merchant storefronts and their admins.
**Insight:** When a filter blocks a denylist of tags, enumerate which tags are missing from the list—<html> is often overlooked—and check every reflection sink including <title>, where breaking out via </title></head> enables event-handler injection.

