CVE-2024-34341
Description
Trix is a rich text editor. The Trix editor, versions prior to 2.1.1, is vulnerable to arbitrary code execution when copying and pasting content from the web or other documents with markup into the editor. The vulnerability stems from improper sanitization of pasted content, allowing an attacker to embed malicious scripts which are executed within the context of the application. Users should upgrade to Trix editor version 2.1.1 or later, which incorporates proper sanitization of input from copied content.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Trix editor prior to 2.1.1 is vulnerable to arbitrary code execution via crafted pasted content due to insufficient sanitization.
Trix, a rich text editor, contains a vulnerability in versions prior to 2.1.1 where insufficient sanitization of pasted content allows execution of arbitrary scripts [4]. The bug originates from the editor's handling of markup from external sources during copy-paste operations, failing to properly escape or strip malicious HTML elements.
An attacker can exploit this flaw by crafting a document with embedded JavaScript and inducing a user to copy and paste it into a Trix editor [2]. No special privileges are required, as the attack vector relies on the user's action. The pasted content is processed by Trix's document model, which prior to the fix did not adequately sanitize attributes like data-trix-* [3].
Successful exploitation leads to arbitrary code execution within the context of the application, potentially enabling data theft, session hijacking, or further compromise of the user's session [4].
Users should upgrade to Trix version 2.1.1 or later, which includes proper input sanitization [2][3]. No workarounds are mentioned, but the fix is straightforward and incorporated into Rails via commit 260cb39 [2].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
trixnpm | >= 2.0.0, < 2.1.1 | 2.1.1 |
trixnpm | >= 0.9.0, < 1.3.2 | 1.3.2 |
actiontextRubyGems | >= 7.0.0.alpha1, < 7.0.8.3 | 7.0.8.3 |
actiontextRubyGems | >= 7.1.0.beta1, < 7.1.3.3 | 7.1.3.3 |
Affected products
5- ghsa-coords4 versionspkg:gem/actiontextpkg:npm/trixpkg:rpm/opensuse/rubygem-actiontext-7.0&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/rubygem-rails-7.0&distro=openSUSE%20Tumbleweed
>= 7.0.0.alpha1, < 7.0.8.3+ 3 more
- (no CPE)range: >= 7.0.0.alpha1, < 7.0.8.3
- (no CPE)range: >= 2.0.0, < 2.1.1
- (no CPE)range: < 7.0.8.4-1.1
- (no CPE)range: < 7.0.8.4-1.1
Patches
61a5c68a14d48Merge pull request #1149 from basecamp/paste-html-sanitize
2 files changed · +22 −1
src/test/system/pasting_test.js+15 −0 modified@@ -104,6 +104,21 @@ testGroup("Pasting", { template: "editor_empty" }, () => { delete window.unsanitized }) + test("paste data-trix-attachment unsafe html", async () => { + window.unsanitized = [] + const pasteData = { + "text/plain": "x", + "text/html": `\ + copy<div data-trix-attachment="{"contentType":"text/html","content":"<img src=1 onerror=window.unsanitized.push(1)>HELLO123"}"></div>me + `, + } + + await pasteContent(pasteData) + await delay(20) + assert.deepEqual(window.unsanitized, []) + delete window.unsanitized + }) + test("prefers plain text when html lacks formatting", async () => { const pasteData = { "text/html": "<meta charset='utf-8'>a\nb",
src/trix/models/html_parser.js+7 −1 modified@@ -40,7 +40,13 @@ const blockForAttributes = (attributes = {}, htmlAttributes = {}) => { const parseTrixDataAttribute = (element, name) => { try { - return JSON.parse(element.getAttribute(`data-trix-${name}`)) + const data = JSON.parse(element.getAttribute(`data-trix-${name}`)) + + if (data.contentType === "text/html" && data.content) { + data.content = HTMLSanitizer.sanitize(data.content).getHTML() + } + + return data } catch (error) { return {} }
841ff19b53f3Merge pull request #1147 from basecamp/sanitize-noscript
2 files changed · +16 −1
src/test/system/pasting_test.js+15 −0 modified@@ -89,6 +89,21 @@ testGroup("Pasting", { template: "editor_empty" }, () => { delete window.unsanitized }) + test("paste unsafe html with noscript", async () => { + window.unsanitized = [] + const pasteData = { + "text/plain": "x", + "text/html": `\ + <div><noscript><div class="123</noscript>456<img src=1 onerror=window.unsanitized.push(1)//"></div></noscript></div> + ` + } + + await pasteContent(pasteData) + await delay(20) + assert.deepEqual(window.unsanitized, []) + delete window.unsanitized + }) + test("prefers plain text when html lacks formatting", async () => { const pasteData = { "text/html": "<meta charset='utf-8'>a\nb",
src/trix/models/html_sanitizer.js+1 −1 modified@@ -4,7 +4,7 @@ import { nodeIsAttachmentElement, removeNode, tagName, walkTree } from "trix/cor const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ") const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ") -const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form".split(" ") +const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" ") export default class HTMLSanitizer extends BasicObject { static sanitize(html, options) {
0c79bcb854b873fac32511eeKeep actiontext depending on trix 1.3.1
2 files changed · +7 −7
actiontext/package.json+3 −3 modified@@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "7.0.8-2", + "version": "7.0.8-3", "description": "Edit and display rich text in Rails applications", "main": "app/assets/javascripts/actiontext.js", "type": "module", @@ -25,13 +25,13 @@ "@rails/activestorage": ">= 7.0.0-alpha1" }, "peerDependencies": { - "trix": "^2.0.0" + "trix": "^1.3.1" }, "devDependencies": { "@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-commonjs": "^19.0.1", "rollup": "^2.35.1", - "trix": "^2.0.0" + "trix": "^1.3.1" }, "scripts": { "build": "rollup --config rollup.config.js"
yarn.lock+4 −4 modified@@ -4974,10 +4974,10 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" -trix@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/trix/-/trix-2.1.1.tgz#688f1213601316cf8b92c5e625d2f562c118c780" - integrity sha512-IljOMGOlRUPg1i5Pk/+x/Ia65ZY7Gw5JxxKCh/4caxG5ZaKuFJCKdn1+TF0efUYfdg+bqWenB/mAYCHjZu0zpQ== +trix@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/trix/-/trix-1.3.2.tgz#9568c3bbda1085b9fcf2619ac41363011493d57f" + integrity sha512-nV8IL6eS/czlaOu9TVIEcblQuPHeuuFpeoO7jFKII5q1pMUXCUGalJtEstS70HSkBSfUXU2vGJUfYXvSItcRCA== tsconfig-paths@^3.14.1: version "3.14.1"
07e6c88cc4deUpgrade Trix to 1.3.2 to fix [CVE-2024-34341][1]
8 files changed · +5228 −10876
actiontext/app/assets/javascripts/trix.js+18 −5275 modifiedactiontext/app/assets/stylesheets/trix.css+20 −374 modifiedactiontext/CHANGELOG.md+5 −0 modified@@ -1,3 +1,8 @@ +* Upgrade Trix to 1.3.2 to fix [CVE-2024-34341](https://github.com/basecamp/trix/security/advisories/GHSA-qjqp-xr96-cj99). + + *Rafael Mendonça França* + + ## Rails 7.0.8.1 (February 21, 2024) ## * No changes.
actiontext/package.json+2 −2 modified@@ -25,13 +25,13 @@ "@rails/activestorage": ">= 7.0.0-alpha1" }, "peerDependencies": { - "trix": "^1.3.1" + "trix": "^2.0.0" }, "devDependencies": { "@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-commonjs": "^19.0.1", "rollup": "^2.35.1", - "trix": "^1.3.1" + "trix": "^2.0.0" }, "scripts": { "build": "rollup --config rollup.config.js"
actiontext/Rakefile+23 −0 modified@@ -18,4 +18,27 @@ Rake::TestTask.new "test:system" do |t| t.verbose = true end +task :vendor_trix do + require "importmap-rails" + require "importmap/packager" + + packager = Importmap::Packager.new(vendor_path: "app/assets/javascripts") + imports = packager.import("trix@^1.3.2", from: "unpkg") + imports.each do |package, url| + url.gsub!("esm.min.js", "umd.js") + puts %(Vendoring "#{package}" to #{packager.vendor_path}/#{package}.js via download from #{url}) + packager.download(package, url) + + css_url = url.gsub("umd.js", "css") + puts %(Vendoring "#{package}" to #{packager.vendor_path}/#{package}.css via download from #{css_url}) + + response = Net::HTTP.get_response(URI(css_url)) + if response.code == "200" + File.open(Pathname.new("app/assets/stylesheets/trix.css"), "w+") do |file| + file.write response.body + end + end + end +end + task default: :test
Gemfile+1 −1 modified@@ -29,7 +29,7 @@ gem "stimulus-rails" gem "turbo-rails" gem "jsbundling-rails" gem "cssbundling-rails" -gem "importmap-rails" +gem "importmap-rails", ">= 1.2.3" gem "tailwindcss-rails" # require: false so bcrypt is loaded only when has_secure_password is used. # This is to avoid Active Model (and by extension the entire framework)
Gemfile.lock+7 −2 modified@@ -314,8 +314,9 @@ GEM image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - importmap-rails (1.1.5) + importmap-rails (2.0.1) actionpack (>= 6.0.0) + activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.6.0) irb (1.6.3) @@ -526,6 +527,10 @@ GEM concurrent-ruby (~> 1.0) tailwindcss-rails (2.0.21) railties (>= 6.0.0) + tailwindcss-rails (2.0.21-x86_64-darwin) + railties (>= 6.0.0) + tailwindcss-rails (2.0.21-x86_64-linux) + railties (>= 6.0.0) terser (1.1.13) execjs (>= 0.3.0, < 3) thin (1.8.1) @@ -592,7 +597,7 @@ DEPENDENCIES google-cloud-storage (~> 1.11) hiredis image_processing (~> 1.2) - importmap-rails + importmap-rails (>= 1.2.3) jsbundling-rails json (>= 2.0.0) libxml-ruby
yarn.lock+5152 −5222 modified
260cb392fc1eUpgrade Trix to 2.1.1 to fix [CVE-2024-34341][1]
3 files changed · +100 −31
actiontext/app/assets/javascripts/trix.js+92 −30 modified@@ -1,6 +1,6 @@ /* -Trix 2.0.7 -Copyright © 2023 37signals, LLC +Trix 2.1.1 +Copyright © 2024 37signals, LLC */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : @@ -9,14 +9,15 @@ Copyright © 2023 37signals, LLC })(this, (function () { 'use strict'; var name = "trix"; - var version = "2.0.7"; + var version = "2.1.1"; var description = "A rich text editor for everyday writing"; var main = "dist/trix.umd.min.js"; var module = "dist/trix.esm.min.js"; var style = "dist/trix.css"; var files = [ "dist/*.css", "dist/*.js", + "dist/*.map", "src/{inspector,trix}/*.js" ]; var repository = { @@ -130,6 +131,7 @@ Copyright © 2023 37signals, LLC code: { tagName: "pre", terminal: true, + htmlAttributes: ["language"], text: { plaintext: true } @@ -1215,7 +1217,7 @@ $\ no-useless-escape, */ const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " "); - const normalizeNewlines = string => string.replace(/\r\n/g, "\n"); + const normalizeNewlines = string => string.replace(/\r\n?/g, "\n"); const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]")); const squishBreakableWhitespace = string => string // Replace all breakable whitespace characters with a space @@ -2144,20 +2146,28 @@ $\ } } createContainerElement(depth) { - let attributes, className; + const attributes = {}; + let className; const attributeName = this.attributes[depth]; const { - tagName + tagName, + htmlAttributes = [] } = getBlockConfig(attributeName); if (depth === 0 && this.block.isRTL()) { - attributes = { + Object.assign(attributes, { dir: "rtl" - }; + }); } if (attributeName === "attachmentGallery") { const size = this.block.getBlockBreakPosition(); className = "".concat(css$1.attachmentGallery, " ").concat(css$1.attachmentGallery, "--").concat(size); } + Object.entries(this.block.htmlAttributes).forEach(_ref => { + let [name, value] = _ref; + if (htmlAttributes.includes(name)) { + attributes[name] = value; + } + }); return makeElement({ tagName, className, @@ -5828,28 +5838,29 @@ $\ class Block extends TrixObject { static fromJSON(blockJSON) { const text = Text.fromJSON(blockJSON.text); - return new this(text, blockJSON.attributes); + return new this(text, blockJSON.attributes, blockJSON.htmlAttributes); } - constructor(text, attributes) { + constructor(text, attributes, htmlAttributes) { super(...arguments); this.text = applyBlockBreakToText(text || new Text()); this.attributes = attributes || []; + this.htmlAttributes = htmlAttributes || {}; } isEmpty() { return this.text.isBlockBreak(); } isEqualTo(block) { if (super.isEqualTo(block)) return true; - return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes); + return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes) && objectsAreEqual(this.htmlAttributes, block === null || block === void 0 ? void 0 : block.htmlAttributes); } copyWithText(text) { - return new Block(text, this.attributes); + return new Block(text, this.attributes, this.htmlAttributes); } copyWithoutText() { return this.copyWithText(null); } copyWithAttributes(attributes) { - return new Block(this.text, attributes); + return new Block(this.text, attributes, this.htmlAttributes); } copyWithoutAttributes() { return this.copyWithAttributes(null); @@ -5866,6 +5877,12 @@ $\ const attributes = this.attributes.concat(expandAttribute(attribute)); return this.copyWithAttributes(attributes); } + addHTMLAttribute(attribute, value) { + const htmlAttributes = Object.assign({}, this.htmlAttributes, { + [attribute]: value + }); + return new Block(this.text, this.attributes, htmlAttributes); + } removeAttribute(attribute) { const { listAttribute @@ -5962,7 +5979,8 @@ $\ toJSON() { return { text: this.text, - attributes: this.attributes + attributes: this.attributes, + htmlAttributes: this.htmlAttributes }; } @@ -6325,6 +6343,11 @@ $\ const range = this.getRangeOfAttachment(attachment); return this.removeAttributeAtRange(attribute, range); } + setHTMLAttributeAtPosition(position, name, value) { + const block = this.getBlockAtPosition(position); + const updatedBlock = block.addHTMLAttribute(name, value); + return this.replaceBlock(block, updatedBlock); + } insertBlockBreakAtRange(range) { let blocks; range = normalizeRange(range); @@ -6793,9 +6816,9 @@ $\ return attributes; }; - const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height class".split(" "); + const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" "); const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" "); - const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form".split(" "); + const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" "); class HTMLSanitizer extends BasicObject { static sanitize(html, options) { const sanitizer = new this(html, options); @@ -6923,15 +6946,21 @@ $\ }; const blockForAttributes = function () { let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let htmlAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const text = []; return { text, - attributes + attributes, + htmlAttributes }; }; const parseTrixDataAttribute = (element, name) => { try { - return JSON.parse(element.getAttribute("data-trix-".concat(name))); + const data = JSON.parse(element.getAttribute("data-trix-".concat(name))); + if (data.contentType === "text/html" && data.content) { + data.content = HTMLSanitizer.sanitize(data.content).getHTML(); + } + return data; } catch (error) { return {}; } @@ -7027,8 +7056,9 @@ $\ } else if (element === this.containerElement || this.isBlockElement(element)) { var _this$currentBlock; const attributes = this.getBlockAttributes(element); + const htmlAttributes = this.getBlockHTMLAttributes(element); if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) { - this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element); + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); this.currentBlockElement = element; } } @@ -7039,9 +7069,10 @@ $\ if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) { if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) { const attributes = this.getBlockAttributes(element); + const htmlAttributes = this.getBlockHTMLAttributes(element); if (element.firstChild) { if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) { - this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element); + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); this.currentBlockElement = element; } else { return this.appendStringWithAttributes("\n"); @@ -7129,8 +7160,9 @@ $\ // Document construction appendBlockForAttributesWithElement(attributes, element) { + let htmlAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; this.blockElements.push(element); - const block = blockForAttributes(attributes); + const block = blockForAttributes(attributes, htmlAttributes); this.blocks.push(block); return block; } @@ -7235,6 +7267,17 @@ $\ } return attributes$1.reverse(); } + getBlockHTMLAttributes(element) { + const attributes$1 = {}; + const blockConfig = Object.values(attributes).find(settings => settings.tagName === tagName(element)); + const allowedAttributes = (blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig.htmlAttributes) || []; + allowedAttributes.forEach(attribute => { + if (element.hasAttribute(attribute)) { + attributes$1[attribute] = element.getAttribute(attribute); + } + }); + return attributes$1; + } findBlockElementAncestors(element) { const ancestors = []; while (element && element !== this.containerElement) { @@ -7830,6 +7873,15 @@ $\ return this.notifyDelegateOfCurrentAttributesChange(); } } + setHTMLAtributeAtPosition(position, attributeName, value) { + var _getBlockConfig; + const block = this.document.getBlockAtPosition(position); + const allowedHTMLAttributes = (_getBlockConfig = getBlockConfig(block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.htmlAttributes; + if (block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes.includes(attributeName)) { + const newDocument = this.document.setHTMLAttributeAtPosition(position, attributeName, value); + this.setDocument(newDocument); + } + } setTextAttribute(attributeName, value) { const selectedRange = this.getSelectedRange(); if (!selectedRange) return; @@ -7877,10 +7929,10 @@ $\ return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0; } canIncreaseNestingLevel() { - var _getBlockConfig; + var _getBlockConfig2; const block = this.getBlock(); if (!block) return; - if ((_getBlockConfig = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig !== void 0 && _getBlockConfig.listAttribute) { + if ((_getBlockConfig2 = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2.listAttribute) { const previousBlock = this.getPreviousBlock(); if (previousBlock) { return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes()); @@ -8521,6 +8573,11 @@ $\ return this.composition.removeCurrentAttribute(name); } + // HTML attributes + setHTMLAtributeAtPosition(position, name, value) { + this.composition.setHTMLAtributeAtPosition(position, name, value); + } + // Nesting level canDecreaseNestingLevel() { @@ -10941,8 +10998,12 @@ $\ }); }, insertReplacementText() { - return this.insertString(this.event.dataTransfer.getData("text/plain"), { - updatePosition: false + const replacement = this.event.dataTransfer.getData("text/plain"); + const domRange = this.event.getTargetRanges()[0]; + this.withTargetDOMRange(domRange, () => { + this.insertString(replacement, { + updatePosition: false + }); }); }, insertText() { @@ -11064,7 +11125,7 @@ $\ return this.toggleDialog(actionName); } else { var _this$delegate2; - return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName); + return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName, element); } } didClickAttributeButton(event, element) { @@ -11509,8 +11570,8 @@ $\ }); } } - toolbarDidInvokeAction(actionName) { - return this.invokeAction(actionName); + toolbarDidInvokeAction(actionName, invokingElement) { + return this.invokeAction(actionName, invokingElement); } toolbarDidToggleAttribute(attributeName) { this.recordFormattingUndoEntry(attributeName); @@ -11579,10 +11640,11 @@ $\ return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN = _this$actions$actionN.test) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN.call(this)); } } - invokeAction(actionName) { + invokeAction(actionName, invokingElement) { if (this.actionIsExternal(actionName)) { return this.notifyEditorElement("action-invoke", { - actionName + actionName, + invokingElement }); } else { var _this$actions$actionN2;
actiontext/app/assets/stylesheets/trix.css+3 −1 modified@@ -334,7 +334,9 @@ trix-editor .attachment__metadata { white-space: nowrap; } .trix-content { - line-height: 1.5; } + line-height: 1.5; + overflow-wrap: break-word; + word-break: break-word; } .trix-content * { box-sizing: border-box; margin: 0;
actiontext/CHANGELOG.md+5 −0 modified@@ -1,3 +1,8 @@ +* Upgrade Trix to 1.3.2 to fix [CVE-2024-34341](https://github.com/basecamp/trix/security/advisories/GHSA-qjqp-xr96-cj99). + + *Rafael Mendonça França* + + ## Rails 7.1.3.2 (February 21, 2024) ## * No changes.
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
15- github.com/advisories/GHSA-qjqp-xr96-cj99ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-34341ghsaADVISORY
- discuss.rubyonrails.org/t/xss-vulnerabilities-in-trix-editor/85803ghsaWEB
- github.com/basecamp/trix/commit/1a5c68a14d48421fc368e30026f4a7918028b7adnvdWEB
- github.com/basecamp/trix/commit/841ff19b53f349915100bca8fcb488214ff93554nvdWEB
- github.com/basecamp/trix/pull/1147nvdWEB
- github.com/basecamp/trix/pull/1149nvdWEB
- github.com/basecamp/trix/releases/tag/v2.1.1nvdWEB
- github.com/basecamp/trix/security/advisories/GHSA-qjqp-xr96-cj99nvdWEB
- github.com/rails/rails/commit/07e6c88cc4defe6f6b8d28e79eb13a518e15b14cghsaWEB
- github.com/rails/rails/commit/260cb392fc1ee91d0b749cff08d1c8d54b230bd3ghsaWEB
- github.com/rails/rails/commit/73fac32511eefdd45d8f00fecc2b8cc5408ea6d5ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/actiontext/CVE-2024-34341.ymlghsaWEB
- rubyonrails.org/2024/5/17/Rails-Versions-7-0-8-2-and-7-1-3-3-have-been-releasedghsaWEB
- rubyonrails.org/2024/5/17/Rails-Versions-7-0-8-3-has-been-releasedghsaWEB
News mentions
0No linked articles in our index yet.