Cross-site scripting (XSS) from unsanitized user content
Cross-site scripting happens when your app takes text a user typed, like a comment, bio, or product review, and renders it as live HTML instead of plain text. If an attacker's input contains a script tag, it runs in every other visitor's browser as if it were your own code.
#What goes wrong
The usual culprit is dangerouslySetInnerHTML in React (or v-html in Vue) fed with content that came from a user rather than your own static data. It's an easy shortcut for rendering rich text, and AI editors reach for it without adding a sanitization step.
#Why it matters
An XSS bug lets an attacker run arbitrary JavaScript in the browser of anyone who views the affected page. That script can steal session cookies, capture keystrokes, or silently perform actions as the logged-in user. It's one of the oldest and still most common ways real apps get compromised.
#How Heimdall checks for this
Heimdall looks for dangerouslySetInnerHTML and similar raw-HTML sinks, and checks whether the content passed in comes from user input or from your own static data. Content already passed through a sanitizer like DOMPurify is not flagged.
#How to fix it
Sanitize any user-supplied HTML before rendering it with a library like DOMPurify or isomorphic-dompurify. If you don't actually need to render HTML, render the text as plain text instead. React escapes plain text by default, which is why dangerouslySetInnerHTML is the exception you have to justify.
Frequently asked questions
Does React protect me from XSS automatically?
Is it safe to render Markdown from users?
What about JSON-LD structured data using dangerouslySetInnerHTML?
Run this check on your own repo
Heimdall scans your GitHub repo for this and 29 other issues in under a minute.
