CVE-2024-22191: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Avo is a framework to create admin panels for Ruby on Rails apps. A stored cross-site scripting (XSS) vulnerability was found in the key_value field of Avo v3.2.3 and v2.46.0. This vulnerability could allow an attacker to execute arbitrary JavaScript code in the victim's browser. The value of the key_value is inserted directly into the HTML code. In the current version of Avo (possibly also older versions), the value is not properly sanitized before it is inserted into the HTML code. This vulnerability could be used to steal sensitive information from victims that could be used to hijack victims' accounts or redirect them to malicious websites. Avo 3.2.4 and 2.47.0 include a fix for this issue. Users are advised to upgrade.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2024-01-16T22:15Z
Repository: https://github.com/avo-hq/avo
Language: JSON
Files changed: app/javascript/js/controllers/fields/key_value_controller.js, package.json, yarn.lock
Commit date: 2024-01-12 14:47:25 +0200
Commit message: security: sanitize key_value field content (#2357)


Diff: diff --git a/app/javascript/js/controllers/fields/key_value_controller.js b/app/javascript/js/controllers/fields/key_value_controller.js
index e048f22b..35619ce4 100644
--- a/app/javascript/js/controllers/fields/key_value_controller.js
+++ b/app/javascript/js/controllers/fields/key_value_controller.js
@@ -1,6 +1,7 @@
 /* eslint-disable max-len */
+import * as DOMPurify from 'dompurify'
 import { Controller } from '@hotwired/stimulus'
 import { castBoolean } from '../../helpers/cast_boolean'
 
 export default class extends Controller {
   static targets = ['input', 'controller', 'rows']
@@ -78,11 +79,11 @@ export default class extends Controller {
   updateKeyValueComponent() {
     let result = ''
     let index = 0
     this.fieldValue.forEach((row) => {
       const [key, value] = row
-      result += this.interpolatedRow(key, value, index)
+      result += this.interpolatedRow(DOMPurify.sanitize(key), DOMPurify.sanitize(value), index)
       index++
     })
     this.rowsTarget.innerHTML = result
     window.initTippy()
   }
diff --git a/package.json b/package.json
index d48f1a7e..245ad1f5 100644
--- a/package.json
+++ b/package.json
@@ -32,10 +32,11 @@
     "chart.js": "^3.9.1",
     "chartkick": "^4.2.0",
     "codemirror": "5.59.1",
     "core-js": "^3.35.0",
     "css-loader": "^6.9.0",
+    "dompurify": "^3.0.8",
     "easymde": "^2.18.0",
     "el-transition": "^0.0.7",
     "esbuild": "^0.14.54",
     "eslint-config-airbnb": "^19.0.4",
     "eslint-import-resolver-alias": "^1.1.2",
diff --git a/yarn.lock b/yarn.lock
index b53787bc..69e8d2ae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2088,10 +2088,15 @@ doctrine@^3.0.0:
   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
   integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
   dependencies:
     esutils "^2.0.2"
 
+dompurify@^3.0.8:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.8.tgz#e0021ab1b09184bc8af7e35c7dd9063f43a8a437"
+  integrity sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==
+
 easymde@^2.18.0:
   version "2.18.0"
   resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.18.0.tgz#ff1397d07329b1a7b9187d2d0c20766fa16b3b1b"
   integrity sha512-IxVVUxNWIoXLeqtBU4BLc+eS/ScYhT1Dcb6yF5Wchoj1iXAV+TIIDWx+NCaZhY7RcSHqDPKllbYq7nwGKILnoA==
   dependencies:

Vulnerable code:       result += this.interpolatedRow(key, value, index)
Fixed code: import * as DOMPurify from 'dompurify'
      result += this.interpolatedRow(DOMPurify.sanitize(key), DOMPurify.sanitize(value), index)
    "dompurify": "^3.0.8",
dompurify@^3.0.8:
  version "3.0.8"
  resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.8.tgz#e0021ab1b09184bc8af7e35c7dd9063f43a8a437"
  integrity sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==