CVE-2022-39232 (published 2022-09-29T21:15Z)

Discourse is an open source discussion platform. Starting with version 2.9.0.beta5 and prior to version 2.9.0.beta10, an incomplete quote can generate a JavaScript error which will crash the current page in the browser in some cases. Version 2.9.0.beta10 added a fix and tests to ensure incomplete quotes won't break the app. As a workaround, the quote can be fixed via the rails console.

CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L)

Weakness information:
cwe_id: NVD-CWE-Other
cwe_name: Other
description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/discourse/discourse
commit_details: repo_url: https://github.com/discourse/discourse
author: Jarek Radosz
author_date: 2022-09-21 14:02:50+02:00
msg: SECURITY: Handle incomplete quote bbcode (#18311)
repository: repo_url: https://github.com/discourse/discourse
repo_name: discourse/discourse
description: A platform for community discussion. Free, open, simple.
repo_language: Ruby
owner: discourse
file_changes: filename: post-cooked.js
change_type: ModificationType.MODIFY
diff: @@ -283,8 +283,9 @@ export default class PostCooked {
         const $title = $(".title", $aside);
 
         // If post/topic is not found then display username, skip controls
-        if (e.classList.contains("quote-post-not-found")) {
-          return (e.querySelector(".title").innerHTML = e.dataset.username);
+        if (e.classList.contains("quote-post-not-found") && $title.length) {
+          e.querySelector(".title").innerHTML = e.dataset.username;
+          return;
         }
 
         // Unless it's a full quote, allow click to expand

programming_language: JavaScript
filename: post-cooked-test.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1,21 @@
+import { module, test } from "qunit";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import { render } from "@ember/test-helpers";
+import { query } from "discourse/tests/helpers/qunit-helpers";
+import { hbs } from "ember-cli-htmlbars";
+
+module("Integration | Component | Widget | post-cooked", function (hooks) {
+  setupRenderingTest(hooks);
+
+  test("quotes with no username and no valid topic", async function (assert) {
+    this.set("args", {
+      cooked: `<aside class=\"quote no-group quote-post-not-found\" data-post=\"1\" data-topic=\"123456\">\n<blockquote>\n<p>abcd</p>\n</blockquote>\n</aside>\n<p>Testing the issue</p>`,
+    });
+
+    await render(
+      hbs`<MountWidget @widget="post-cooked" @args={{this.args}} />`
+    );
+
+    assert.strictEqual(query("blockquote").innerText, "abcd");
+  });
+});

programming_language: TypeScript
filename: pretty-text-test.js
change_type: ModificationType.MODIFY
diff: @@ -442,6 +442,19 @@ eviltrout</p>
     );
   });
 
+  test("Incomplete quotes", function (assert) {
+    assert.cookedOptions(
+      '[quote=", post: 1"]\na quote\n[/quote]',
+      { topicId: 2 },
+      `<aside class=\"quote no-group\" data-post=\"1\">
+<blockquote>
+<p>a quote</p>
+</blockquote>
+</aside>`,
+      "works with missing username"
+    );
+  });
+
   test("Mentions", function (assert) {
     assert.cooked(
       "Hello @sam",

programming_language: JavaScript