hitoshura25/cvefixes huggingface dataset:
CVE-2023-23622 (Ruby, published 2023-03-17T15:15Z)
Description: value: Discourse is an open-source discussion platform. Prior to version 3.0.1 of the `stable` branch and version 3.1.0.beta2 of the `beta` and `tests-passed` branches, the count of topics displayed for a tag is a count of all regular topics regardless of whether the topic is in a read restricted category or not. As a result, any users can technically poll a sensitive tag to determine if a new topic is created in a category which the user does not have excess to. 

In version 3.0.1 of the `stable` branch and version 3.1.0.beta2 of the `beta` and `tests-passed` branches, the count of topics displayed for a tag defaults to only counting regular topics which are not in read restricted categories. Staff users will continue to see a count of all topics regardless of the topic's category read restrictions.
Severity: nan (CVSS v3 base score: 4.3)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/discourse/discourse
Files changed:
app/controllers/tags_controller.rb
spec/requests/tags_controller_spec.rb
Commit message: SECURITY: only show restricted tag lists to authorized users (#20004)

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>

Vulnerable code:
  before_action :ensure_visible, only: %i[show info]

Fixed code:
  before_action :ensure_visible, only: [:show, :info, *show_methods]

        it "returns a 404 when tag is restricted" do
          tag_group = Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: ["test"])

          get "/tag/test/l/latest.json"
          expect(response.status).to eq(404)

          sign_in(admin)

          get "/tag/test/l/latest.json"
          expect(response.status).to eq(200)
        end


    it "returns a 404 if tag is restricted" do
      tag_group = Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: ["test"])

      get "/tag/test/l/top.json"
      expect(response.status).to eq(404)

      sign_in(admin)

      get "/tag/test/l/top.json"
      expect(response.status).to eq(200)
    end
CVE-2023-23624 (Ruby, published 2023-01-28T00:15Z)
Description: value: Discourse is an open-source discussion platform. Prior to version 3.0.1 on the `stable` branch and version 3.1.0.beta2 on the `beta` and `tests-passed` branches, someone can use the `exclude_tag param` to filter out topics and deduce which ones were using a specific hidden tag. This affects any Discourse site using hidden tags in public categories. This issue is patched in version 3.0.1 on the `stable` branch and version 3.1.0.beta2 on the `beta` and `tests-passed` branches. As a workaround, secure any categories that are using hidden tags, change any existing hidden tags to not include private data, or remove any hidden tags currently in use.
Severity: nan (CVSS v3 base score: 5.3)
Weakness: CWE-200 \u2014 Exposure of Sensitive Information to an Unauthorized Actor
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Repository: https://github.com/discourse/discourse
Files changed:
lib/topic_query.rb
spec/lib/topic_query_spec.rb
Commit message: SECURITY: Update to exclude tag topic filter (#20006)

Ignores tags specified in exclude_tag topics param that a user does not
have access to.

Co-authored-by: Blake Erickson <o.blakeerickson@gmail.com>

Vulnerable code:
      result = result.where(<<~SQL, name: @options[:exclude_tag]) if @options[:exclude_tag].present?
        topics.id NOT IN (
          SELECT topic_tags.topic_id
          FROM topic_tags
          INNER JOIN tags ON tags.id = topic_tags.tag_id
          WHERE tags.name = :name
        )
        SQL

Fixed code:
      if @options[:exclude_tag].present? &&
           !DiscourseTagging.hidden_tag_names(@guardian).include?(@options[:exclude_tag])
        result = result.where(<<~SQL, name: @options[:exclude_tag])
          topics.id NOT IN (
            SELECT topic_tags.topic_id
            FROM topic_tags
            INNER JOIN tags ON tags.id = topic_tags.tag_id
            WHERE tags.name = :name
          )
          SQL
      end
      fab!(:tag_group) do
        Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [other_tag.name])
      end
      it "does not exclude a tagged topic without permission" do
        topics = TopicQuery.new(user, exclude_tag: other_tag.name).list_latest.topics
        expect(topics.map(&:id)).to include(tagged_topic2.id)
      end
CVE-2023-36818 (Ruby, published 2023-07-14T22:15Z)
Description: value: Discourse is an open source discussion platform. In affected versions a request to create or update custom sidebar section can cause a denial of service. This issue has been patched in commit `52b003d915`. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/discourse/discourse
Files changed:
app/controllers/sidebar_sections_controller.rb
app/models/sidebar_section.rb
config/site_settings.yml
spec/requests/sidebar_sections_controller_spec.rb
Commit message: SECURITY: limit amount of links in custom sidebar section (#22543)

Custom sidebar section can have maximum of 50 links

Co-authored-by: Krzysztof Kotlarek <kotlarek.krzysztof@gmail.com>

Vulnerable code:
  accepts_nested_attributes_for :sidebar_urls, allow_destroy: true

Fixed code:
  rescue ActiveRecord::NestedAttributes::TooManyRecords => e
    render_json_error(e.message)
  rescue ActiveRecord::NestedAttributes::TooManyRecords => e
    render_json_error(e.message)
  accepts_nested_attributes_for :sidebar_urls,
                                allow_destroy: true,
                                limit: -> { SiteSetting.max_sidebar_section_links }
  max_sidebar_section_links:
    default: 50
    hidden: true
    it "validates max number of links" do
      SiteSetting.max_sidebar_section_links = 5

      sign_in(user)

      links =
        6.times.map do
          { icon: "external-link-alt", name: "My preferences", value: "/my/preferences" }
        end

      post "/sidebar_sections.json", params: { title: "custom section", links: links }

      expect(response.status).to eq(422)
      expect(response.parsed_body["errors"]).to eq(
        ["Maximum 5 records are allowed. Got 6 records instead."],
      )
    end

    it "validates limit of links" do
      SiteSetting.max_sidebar_section_links = 5

      sign_in(user)

      links =
        6.times.map do
          { icon: "external-link-alt", name: "My preferences", value: "/my/preferences" }
        end

      put "/sidebar_sections/#{sidebar_section.id}.json",
          params: {
            title: "custom section",
            links: links,
          }

      expect(response.status).to eq(422)
      expect(response.parsed_body["errors"]).to eq(
        ["Maximum 5 records are allowed. Got 6 records instead."],
      )
    end
CVE-2023-37904 (Ruby, published 2023-07-28T16:15Z)
Description: value: Discourse is an open source discussion platform. Prior to version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches, more users than permitted could be created from invite links. The issue is patched in version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches. As a workaround, use restrict to email address invites.
Severity: nan (CVSS v3 base score: 3.1)
Weakness: CWE-362 \u2014 Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
The product contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
Repository: https://github.com/discourse/discourse
Files changed:
app/controllers/invites_controller.rb
app/models/invite_redeemer.rb
spec/requests/invites_controller_spec.rb
Commit message: SECURITY: Handle concurrent invite accepts

Raise an error on concurrent invite accept attempts.


Vulnerable code:
      rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved, Invite::UserExists => e
      Invite.increment_counter(:redemption_count, invite.id)

Fixed code:
      rescue ActiveRecord::RecordInvalid,
             ActiveRecord::RecordNotSaved,
             ActiveRecord::LockWaitTimeout,
             Invite::UserExists => e
      invite.with_lock("FOR UPDATE NOWAIT") do
        Invite.increment_counter(:redemption_count, invite.id)
        invite.save!
      end
      it "does not create multiple users for a single use invite" do
        user_count = User.count

        2
          .times
          .map do
            Thread.new do
              put "/invites/show/#{invite.invite_key}.json",
                  params: {
                    email: "test@example.com",
                    password: "verystrongpassword",
                  }
            end
          end
          .each(&:join)

        expect(invite.reload.max_redemptions_allowed).to eq(1)
        expect(invite.reload.redemption_count).to eq(1)
        expect(User.count).to eq(user_count + 1)
      end
CVE-2023-37906 (Ruby, published 2023-07-28T16:15Z)
Description: value: Discourse is an open source discussion platform. Prior to version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches, a malicious user can edit a post in a topic and cause a DoS with a carefully crafted edit reason. The issue is patched in version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches. There are no known workarounds for this vulnerability.
Severity: nan (CVSS v3 base score: 4.3)
Weakness: CWE-770 \u2014 Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
Repository: https://github.com/discourse/discourse
Files changed:
app/models/post.rb
spec/models/post_spec.rb
Commit message: SECURITY: Limit length of edit reason column


Vulnerable code:

Fixed code:
  validates :edit_reason, length: { maximum: 1000 }
  it { is_expected.to validate_length_of(:edit_reason).is_at_most(1000) }
CVE-2023-38685 (Ruby, published 2023-07-28T16:15Z)
Description: value: Discourse is an open source discussion platform. Prior to version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches, information about restricted-visibility topic tags could be obtained by unauthorized users. The issue is patched in version 3.0.6 of the `stable` branch and version 3.1.0.beta7 of the `beta` and `tests-passed` branches.
Severity: nan (CVSS v3 base score: 4.3)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/discourse/discourse
Files changed:
app/models/topic.rb
app/serializers/concerns/topic_tags_mixin.rb
app/views/list/list.erb
spec/requests/list_controller_spec.rb
Commit message: SECURITY: Hide restricted tags in noscript view

The hidden tags are usually filtered out by the serializer, but the
noscript view uses the topic objects instead of the serialized objects.


Vulnerable code:
          topic.tags.sort_by(&:name)
          topic.tags.sort_by { |tag| tag.public_send(topic_count_column) }.reverse
    tags = tags.reject { |tag| scope.hidden_tag_names.include?(tag[:name]) } if !scope.is_staff?
              <% if t.tags %>
                  <% t.tags.each_with_index do |tag, index| %>
                    <% if index < t.tags.size - 1 %>,&nbsp;<% end %>

Fixed code:
  def visible_tags(guardian)
    tags.reject { |tag| guardian.hidden_tag_names.include?(tag[:name]) }
  end


    tags = topic.visible_tags(scope)

          tags.sort_by(&:name)
          tags.sort_by { |tag| tag.public_send(topic_count_column) }.reverse

              <% if tags = t.visible_tags(guardian) %>
                  <% tags.each_with_index do |tag, index| %>
                    <% if index < tags.size - 1 %>,&nbsp;<% end %>

    context "with topics with tags" do
      let(:tag_group) { Fabricate.build(:tag_group) }
      let(:tag_group_permission) { Fabricate.build(:tag_group_permission, tag_group: tag_group) }
      let(:restricted_tag) { Fabricate(:tag) }
      let(:public_tag) { Fabricate(:tag) }

      before do
        tag_group.tag_group_permissions << tag_group_permission
        tag_group.save!
        tag_group_permission.tag_group.tags << restricted_tag
        topic.tags << [public_tag, restricted_tag]
      end

      it "does not show hidden tags" do
        get "/latest"

        expect(response.status).to eq(200)
        expect(response.body).to include(public_tag.name)
        expect(response.body).not_to include(restricted_tag.name)
      end
    end
CVE-2023-46130 (Other, 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, some theme components allow users to add svgs with unlimited `height` attributes, and this can affect the availability of subsequent replies in a topic. Most Discourse instances are unaffected, only instances with the svgbob or the mermaid theme component are within scope. The issue is patched in version 3.1.3 of the `stable` branch and version 3.2.0.beta3 of the `beta` and `tests-passed` branches. As a workaround, disable or remove the relevant theme components. 
Severity: nan (CVSS v3 base score: 5.4)
Weakness: CWE-770 \u2014 Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
Repository: https://github.com/discourse/discourse
Files changed:
app/assets/stylesheets/common/base/topic-post.scss
Commit message: SECURITY: Limit height of pre/svg elements

Ensures posts cannot have SVG or PRE elements that are too tall.


Vulnerable code:

Fixed code:

  svg {
    max-height: 2000px;
  }
  max-height: 2000px;
CVE-2023-47120 (Ruby, published 2023-11-10T16:15Z)
Description: value: Discourse is an open source platform for community discussion. In versions 3.1.0 through 3.1.2 of the `stable` branch and versions 3.1.0,beta6 through 3.2.0.beta2 of the `beta` and `tests-passed` branches, Redis memory can be depleted by crafting a site with an abnormally long favicon URL and drafting multiple posts which Onebox it. The issue is patched in version 3.1.3 of the `stable` branch and version 3.2.0.beta3 of the `beta` and `tests-passed` branches. There are no known workarounds.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-770 \u2014 Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
Repository: https://github.com/discourse/discourse
Files changed:
lib/onebox.rb
lib/onebox/engine/standard_embed.rb
lib/url_helper.rb
spec/lib/onebox/engine/standard_embed_spec.rb
spec/lib/url_helper_spec.rb
Commit message: SECURITY: Prevent Onebox cache overflow by limiting downloads and URL lengths


Vulnerable code:
    max_download_kb: (10 * 1024), # 10MB
        Onebox::Helpers.get_absolute_image_url(favicon, url)
  MAX_URL_LENGTH = 100_000
  def mocked_html_doc(twitter_data: nil)
    stub_favicon(html_doc)
  def stub_favicon(html_doc)
      .returns([])
      expect do UrlHelper.normalized_encode("https://#{"a" * 100_000}.com") end.to raise_error(

Fixed code:
    max_download_kb: 2048, # 2MB
        return nil if favicon.blank?

        absolute_url = Onebox::Helpers.get_absolute_image_url(favicon, url)

        return nil if absolute_url.length > UrlHelper::MAX_URL_LENGTH

        absolute_url
  MAX_URL_LENGTH = 2_000
    it "sets favicon URL" do
      html_doc =
        mocked_html_doc(
          twitter_data: {
            "name" => "twitter:url",
            "content" => "cool.url",
          },
          favicon_url: "https://favicon.co/default.ico",
        )
      Onebox::Helpers.stubs(fetch_html_doc: html_doc)

      expect(instance.raw).to eq({ url: "cool.url", favicon: "https://favicon.co/default.ico" })
    end

    it "ignores suspiciously long favicon URLs" do
      html_doc =
        mocked_html_doc(
          twitter_data: {
            "name" => "twitter:url",
            "content" => "cool.url",
          },
          favicon_url: "https://favicon.co/#{"a" * 2_000}.ico",
        )
      Onebox::Helpers.stubs(fetch_html_doc: html_doc)

      expect(instance.raw).to eq({ url: "cool.url" })
    end

  def mocked_html_doc(twitter_data: nil, favicon_url: nil)
    stub_favicon(html_doc, favicon_url)
  def stub_favicon(html_doc, favicon_url = nil)
      .returns([{ "href" => favicon_url }.compact])
      expect do UrlHelper.normalized_encode("https://#{"a" * 2_000}.com") end.to raise_error(
CVE-2023-47121 (Ruby, published 2023-11-10T16: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, the embedding feature is susceptible to server side request forgery. The issue is patched in version 3.1.3 of the `stable` branch and version 3.2.0.beta3 of the `beta` and `tests-passed` branches. As a workaround, disable the Embedding feature.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-918 \u2014 Server-Side Request Forgery (SSRF)
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Repository: https://github.com/discourse/discourse
Files changed:
app/models/topic_embed.rb
spec/models/topic_embed_spec.rb
Commit message: SECURITY: SSRF vulnerability in TopicEmbed

Block redirects when making the final request in TopicEmbed to prevent Server Side Request Forgery (SSRF)


Vulnerable code:
      html = uri.read
    rescue OpenURI::HTTPError, Net::OpenTimeout

Fixed code:
      html = FinalDestination::HTTP.get(uri)
    rescue OpenURI::HTTPError, Net::OpenTimeout, FinalDestination::SSRFDetector::DisallowedIpError

      it "doesn't follow redirect when making request" do
        FinalDestination.any_instance.stubs(:resolve).returns(URI("https://redirect.com"))
        stub_request(:get, "https://redirect.com/").to_return(
          status: 301,
          body: "<title>Moved permanently</title>",
          headers: {
            "Location" => "https://www.example.org/",
          },
        )
        response = TopicEmbed.find_remote(url)
        expect(response.title).to eq("Moved permanently")
      end
CVE-2023-49099 (Ruby, published 2024-01-12T21:15Z)
Description: value: Discourse is a platform for community discussion. Under very specific circumstances, secure upload URLs associated with posts can be accessed by guest users even when login is required. This vulnerability has been patched in 3.2.0.beta4 and 3.1.4.
Severity: nan (CVSS v3 base score: 4.3)
Weakness: CWE-284 \u2014 Improper Access Control
The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
Repository: https://github.com/discourse/discourse
Files changed:
app/controllers/uploads_controller.rb
spec/requests/uploads_controller_spec.rb
Commit message: SECURITY: Prevent guest users from accessing secure uploads when login required


Vulnerable code:

Fixed code:
      raise Discourse::InvalidAccess if current_user.nil? && SiteSetting.login_required
        context "when login is required and user is not signed in" do
          let(:post) { Fabricate(:post) }

          before do
            SiteSetting.login_required = true
            upload.update(access_control_post_id: post.id)
          end

          it "returns a 403" do
            get secure_url
            expect(response.status).to eq(403)
          end
        end
CVE-2024-24748 (Ruby, published 2024-03-15T20:15Z)
Description: value: Discourse is an open source platform for community discussion. In affected versions an attacker can learn that a secret subcategory exists under a public category which has no public subcategories. The issue is patched in the latest stable, beta and tests-passed version of Discourse. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/discourse/discourse
Files changed:
app/models/category_list.rb
spec/models/category_list_spec.rb
Commit message: SECURITY: Don't disclose the existence of secret subcategories


Vulnerable code:
      category.has_children = category.subcategories.present?

Fixed code:
    parent_ids =
      Category
        .secured(@guardian)
        .where(parent_category_id: categories_with_descendants.map(&:id))
        .pluck("DISTINCT parent_category_id")
        .to_set

      category.has_children = parent_ids.include?(category.id)
  context "when a category has a secret subcategory" do
    fab!(:category)

    fab!(:secret_subcategory) do
      cat = Fabricate(:category, parent_category: category)
      cat.set_permissions(admins: :full)
      cat.save!
      cat
    end

    let(:admin_category_list) { CategoryList.new(Guardian.new(admin), include_topics: true) }

    it "doesn't set has_children when an unpriveleged user is querying" do
      found = category_list.categories.find { |c| c.id == category.id }
      expect(found.has_children).to eq(false)
    end

    it "sets has_children when an admin is querying" do
      found = admin_category_list.categories.find { |c| c.id == category.id }
      expect(found.has_children).to eq(true)
    end
  end