# XSS in steam react chat client

Steam chat's [url] BBCode allowed arbitrary URIs; chaining a whitelisted codepen OEMBED embed with steam://openexternalforpid/10400/ achieved remote code execution on victims.

- Payout: $7,500
- Severity: critical
- Program: Valve
- Credited: zemnmez
- Disclosed: 2019-01-07
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/409850
- Library page: https://bugbountylibrary.com/r/h1%3A409850
- Tags: domain:desktop impact:rce kind:bounty platform:hackerone sev:critical tech:chromium tech:react technique:chained technique:source-review vuln:command-injection vuln:rce vuln:xss

**Target:** Steam chat client (React/CEF) BBCode renderer and steam:// protocol handler
**Root cause:** BBCode [url] tag rendered arbitrary URI schemes into anchor hrefs without scheme allowlisting, and the Steam Web Helper's openexternalforpid handler passed attacker-controlled URIs to the OS shell without sanitization.
**Steps:**
1. Open https://steamcommunity.com/chat with DevTools; observe binary WebSocket and React rendering.
2. Set breakpoints on dangerouslySetInnerHTML and XHR; note client renders sent message then overwrites with server response.
3. Enumerate BBCode tags; find [url=xxx] accepted with arbitrary schemes including javascript: and steam://.
4. javascript: stripped by CEF; pivot to steam:// URIs which execute without confirmation prompt in chat client.
5. Send codepen.io OEMBED embed (whitelisted by Embedly) to run JS in Steam Web Helper context.
6. Binary-grep Steam folder for protocol strings; find steam://openexternalforpid/%s/%s.
7. Watch Steam console while sending jarfile: link; observe internal call steam://openexternalforpid/10400/jarfile:...
8. Send [url=steam://openexternalforpid/10400/cmd.exe] to victim; cmd.exe launches on their machine.
**How found:** Noticed chat used binary WebSocket and React; set breakpoints on dangerouslySetInnerHTML and XHR to trace BBCode rendering. Found [url] accepted arbitrary schemes. javascript: was stripped, so pivoted to steam:// URIs. Binary-grepped Steam for protocol strings, found openexternalforpid/%s/%s, then accidentally saw in the Steam console that jarfile: links were internally rewritten to steam://openexternalforpid/10400/jarfile:..., revealing the magic PID and RCE path.
**Exploitation:** Attacker sends a chat message containing a [url] BBCode link to steam://openexternalforpid/10400/<command>. When victim clicks, Steam Web Helper invokes the OS with the URI, launching arbitrary executables (e.g. cmd.exe) on the victim's Windows host. Alternatively a codepen.io OEMBED embed executes JS in the privileged web helper context.
**Escalation:** Chained stored XSS/URI injection -> steam:// protocol handler -> openexternalforpid with magic PID 10400 -> arbitrary OS command execution.
**Insight:** When a desktop app wraps a browser, watch the Steam/OS console for internal protocol rewrites of your input—those reveal undocumented privileged handlers (like openexternalforpid with a fixed PID) that bypass browser-level scheme filtering.
