# Passive stored XSS at broadcast room

Unfiltered pipe in app names let a broadcaster forge a javascript: href in the chat header, executing stored XSS on viewers via two chained clicks.

- Payout: hidden
- Severity: high
- Program: Chaturbate
- Found by: skavans
- Disclosed: 2018-11-06
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/423797
- Library page: https://bugbountylibrary.com/r/h1%3A423797
- Tags: area:web domain:web impact:ato kind:bounty platform:hackerone sev:high technique:chained vuln:xss

**Target:** Broadcast room chat header app links
**Root cause:** The app_info_json parameter splits app name and details link on `|` without filtering, so an app name containing `|javascript:...` becomes the href of the rendered anchor.
**Steps:**
1. Set room title to `alert('XSS by skavans at ' + document.domain)`
2. Create/run app named `1|javascript:b='#roomtitle';0`
3. Create/run second app named `2|javascript:eval($(b).text())`
4. Start broadcasting, open room as victim
5. Click link `1`, then link `2`; XSS fires
**How found:** Noticed `app_info_json` uses `|` as a delimiter and is rendered into an anchor href unfiltered; tested injecting `javascript:` via app name.
**Exploitation:** Broadcaster crafts two apps whose names inject javascript: hrefs into the chat header; victim clicks link 1 to store the room title selector in variable b, then link 2 evals the title text, executing attacker JS in the victim's session.
**Escalation:** Split the payload across two app links to bypass the 32-character app name limit, using the room subject as payload storage.
**Insight:** When a delimiter-separated field is rendered into an href, inject the delimiter to control the scheme; if length-limited, split payload across multiple attacker-controlled fields and stage data in another user-controlled element like the room title.

