# XSS on internal: privileged origin through reader mode

Reader mode loading template leaked uuidKey via Referer, and SessionRestoreHandler failed to validate javascript: URLs, yielding XSS on internal://local origin.

- Payout: hidden
- Severity: high
- Program: Brave Software
- Found by: nishimunea
- Disclosed: 2023-06-22
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/1438028
- Library page: https://bugbountylibrary.com/r/h1%3A1438028
- Tags: area:mobile domain:browser domain:mobile impact:privesc kind:bounty platform:hackerone sev:high tech:ios technique:chained technique:source-review vuln:info-disclosure vuln:xss

**Target:** iOS browser app (Reader mode templates, SessionRestoreHandler)
**Root cause:** ReaderViewLoading.html lacks the referrer=never meta tag present in Reader.html, leaking the uuidKey in the URL via Referer; SessionRestoreHandler restores a URL without validating its scheme, so a javascript: URL executes on the internal: origin.
**Steps:**
1. Visit https://csrf.jp/brave/reader_uuid_leakage.php and open it in Reader mode
2. Long-tap a hyperlink and choose 'Open in New Private Tab'
3. Wait, then tap 'Load original page' to trigger ReaderViewLoading.html
4. Observe uuidKey leaked through the REFERER header
5. Click the exploit URL containing a `javascript:` payload
6. Payload executes on `internal://local`
**How found:** Compared the two Reader HTML templates and noticed ReaderViewLoading.html omitted the referrer=never meta tag; separately code-read SessionRestoreHandler.swift and saw no URL scheme validation before restore.
**Exploitation:** Attacker page opened in Reader mode leaks the uuidKey via the missing referrer policy in ReaderViewLoading.html; the stolen key is used to construct a reader-mode URL whose restored session URL is a javascript: payload, executed on the privileged internal: origin.
**Escalation:** Chains an info leak (uuidKey) with an unvalidated URL restore to elevate from web content to the privileged internal: origin.
**Insight:** When a product ships multiple near-identical templates, diff them for security headers one copy forgot; and audit any 'restore URL' path for missing scheme allowlisting since javascript:/data: URLs inherit the privileged origin.
