# Stored XSS in posts because of absence of oembed variables values escaping

Discourse onebox rendered unescaped oEmbed JSON fields into raw HTML, so a crafted oEmbed endpoint injected a stored XSS payload into any post.

- Payout: hidden
- Severity: high
- Program: Discourse
- Found by: skavans
- Disclosed: 2017-01-20
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/197914
- Library page: https://bugbountylibrary.com/r/h1%3A197914
- Tags: area:web domain:web impact:integrity kind:bounty platform:hackerone sev:high tech:ruby technique:oob-exfil vuln:xss

**Target:** Onebox oEmbed parser (whitelisted_generic_onebox.rb)
**Root cause:** The whitelisted generic onebox engine interpolates oEmbed JSON values (description, image, dimensions) into raw HTML without escaping, so attacker-controlled oEmbed responses break out of attributes.
**Steps:**
1. Host a page containing `<link type='application/json+oembed' href='http://89.223.28.48/oembed.json'>`.
2. Serve oembed.json with `"description": "descr' onerror='alert(/XSS by skavans/)"`.
3. Paste `http://89.223.28.48/oembed_video.html?uncache` into a Discourse post and save.
4. Onebox fetches the oEmbed JSON and injects the unescaped description into the rendered HTML, firing the onerror handler.
**How found:** Noticed the onebox engine builds raw HTML from oEmbed variables and tested whether a self-hosted oEmbed endpoint's JSON values were escaped.
**Exploitation:** Attacker controls both the linked page and its oEmbed JSON; when any user posts the URL, Discourse's server-side onebox fetches the JSON and renders the unescaped description attribute, executing script in viewers' browsers (stored XSS).
**Insight:** When a server-side unfurler fetches attacker-supplied oEmbed/OpenGraph metadata and interpolates it into HTML, control the metadata endpoint and inject quote-breaking payloads into every field (description, image, dimensions), not just the obvious title.

