CVE-2023-45806 (Ruby, published 2023-11-10T15:15Z)
Description: value: Discourse is an open source platform for community discussion. Prior to version 3.1.3 of the `stable` branch and version 3.2.0.beta3 of the `beta` and `tests-passed` branches, if a user has been quoted and uses a `|` in their full name, they might be able to trigger a bug that generates a lot of duplicate content in all the posts they've been quoted by updating their full name again. Version 3.1.3 of the `stable` branch and version 3.2.0.beta3 of the `beta` and `tests-passed` branches contain a patch for this issue. No known workaround exists, although one can stop the "bleeding" by ensuring users only use alphanumeric characters in their full name field.
Severity: nan (CVSS v3 base score: 5.4)
Weakness: CWE-1333 \u2014 Inefficient Regular Expression Complexity
The product uses a regular expression with an inefficient, possibly exponential worst-case computational complexity that consumes excessive CPU cycles.
Repository: https://github.com/discourse/discourse
Files changed:
lib/quote_rewriter.rb
spec/jobs/change_display_name_spec.rb
Commit message: SECURITY: escape display names

Ensure we escape the display names before passing it to the regexp used to update
quotes whenever a user change their display name.


Vulnerable code:
        /(?<pre>\[quote\s*=\s*["'']?.*username:)#{old_username}(?<post>\,?[^\]]*\])/i,
        /(?<pre>\[quote\s*=\s*["'']?)#{old_username}(?<post>\,?[^\]]*\])/i,
    pattern = /(?<=\s)#{PrettyText::Helpers.format_username(old_username)}(?=:)/i
    pattern = /(?<pre>\[quote\s*=\s*["'']?)#{old_display_name}(?<post>\,[^\]]*username[^\]]*\])/i
    pattern = /(?<=\s)#{PrettyText::Helpers.format_username(old_display_name)}(?=:)/i
  let(:user) { Fabricate(:user, username: "codinghorror", name: "Jeff") }
    [quote="Jeff, post:1, topic:#{quoted_post.topic.id}, username:codinghorror"]
    [quote="Jeff, post:1, topic:#{quoted_post.topic.id}, username:codinghorror"]
  let(:args) { { user_id: user.id, old_name: "Jeff", new_name: "Mr. Atwood" } }
          [quote="Mr. Atwood, post:1, topic:#{quoted_post.topic.id}, username:codinghorror"]
          <aside class="quote no-group" data-username="codinghorror" data-post="1" data-topic="#{quoted_post.topic.id}">
          <img loading="lazy" alt="" width="24" height="24" src="#{avatar_url}" class="avatar"> Mr. Atwood:</div>
          [quote="Mr. Atwood, post:1, topic:#{quoted_post.topic.id}, username:codinghorror"]

Fixed code:
    escaped_old_username = Regexp.escape(old_username)
        /(?<pre>\[quote\s*=\s*["'']?.*username:)#{escaped_old_username}(?<post>\,?[^\]]*\])/i,
        /(?<pre>\[quote\s*=\s*["'']?)#{escaped_old_username}(?<post>\,?[^\]]*\])/i,
    formatted_old_username = PrettyText::Helpers.format_username(old_username)
    escaped_old_username = Regexp.escape(formatted_old_username)
    pattern = /(?<=\s)#{escaped_old_username}(?=:)/i
    escaped_old_display_name = Regexp.escape(old_display_name)
    pattern =
      /(?<pre>\[quote\s*=\s*["'']?)#{escaped_old_display_name}(?<post>\,[^\]]*username[^\]]*\])/i
    formatted_old_display_name = PrettyText::Helpers.format_username(old_display_name)
    escaped_old_display_name = Regexp.escape(formatted_old_display_name)
    pattern = /(?<=\s)#{escaped_old_display_name}(?=:)/i
  let(:username) { "codinghorror" }
  let(:old_display_name) { "|| Jeff ||" }
  let(:new_display_name) { "|| Mr. Atwood ||" }

  let(:user) { Fabricate(:user, username: username, name: old_display_name) }
    [quote="#{old_display_name}, post:1, topic:#{quoted_post.topic.id}, username:#{username}"]
    [quote="#{old_display_name}, post:1, topic:#{quoted_post.topic.id}, username:#{username}"]
  let(:args) { { user_id: user.id, old_name: old_display_name, new_name: new_display_name } }
          [quote="#{new_display_name}, post:1, topic:#{quoted_post.topic.id}, username:#{username}"]
          <aside class="quote no-group" data-username="#{username}" data-post="1" data-topic="#{quoted_post.topic.id}">
          <img loading="lazy" alt="" width="24" height="24" src="#{avatar_url}" class="avatar"> #{new_display_name}:</div>
          [quote="#{new_display_name}, post:1, topic:#{quoted_post.topic.id}, username:#{username}"]