On this page
The core idea
Cross-site scripting (XSS) lets an attacker run their script in another user's browser, where it can read data the page shows or act as that user. It occurs when untrusted data is inserted into HTML, attributes, URLs or scripts without being encoded for that context. Modern frameworks such as React escape text by default. Risk comes from features that insert raw HTML, such as dangerouslySetInnerHTML or innerHTML, from building URLs or script content from user input and from rendering rich text without sanitisation.
A practical approach
Step 1
Render untrusted data as text through your framework's normal binding, which escapes it.
Step 2
Search the codebase for raw HTML insertion, such as dangerouslySetInnerHTML, innerHTML and v-html, and justify each use.
Step 3
When you must render user-provided HTML, sanitise it with a maintained library configured with an allow-list of tags and attributes.
Step 4
Validate URLs before using them in href or src, allowing only expected schemes such as https.
Step 5
Add a Content Security Policy that restricts script sources, as a second layer of defence.
Worked example
A course discussion feature renders posts with Markdown converted to HTML and inserted with dangerouslySetInnerHTML. A test post containing an image tag with an onerror attribute runs JavaScript for everyone who views the thread. Passing the converted HTML through a sanitiser with an allow-list, and adding a Content Security Policy, blocks the payload while keeping formatting.
A mistake to avoid
Do not try to block XSS by removing the word 'script' or a few characters from input. Attackers have many ways to run code, and blacklist filters are routinely bypassed. Encode on output and sanitise with a proper library.
Try it yourself
Search your project for places where HTML is inserted without escaping. For each, determine whether the data can be influenced by users, and either remove the raw insertion or add sanitisation and a test with a malicious payload.
Your implementation checklist
- Untrusted data is rendered through escaping bindings
- Every raw HTML insertion is reviewed and justified
- User HTML is sanitised with an allow-list
- URLs from users are validated by scheme
- A Content Security Policy limits script sources
Share or cite this guide
Innovate with Ajay Editorial (2026-10-07). Prevent Cross-Site Scripting by Escaping Output in Context. https://innovatewithajay.com/blogs/prevent-xss-by-escaping-output-in-context
