Heimdall Scan logo, AI security scanner for vibe coders
Heimdall ScanOpen Beta
CriticalAPI Hardening

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.