CVE-2023-23622 (published 2023-03-17T15:15Z)

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. \n\nIn 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.

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

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/discourse/discourse
commit_details: repo_url: https://github.com/discourse/discourse
author: Bianca Nenciu
author_date: 2023-01-25 18:55:55+02:00
msg: SECURITY: only show restricted tag lists to authorized users (#20004)

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
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: tags_controller.rb
change_type: ModificationType.MODIFY
diff: @@ -5,12 +5,13 @@ class TagsController < ::ApplicationController
   include TopicQueryParams
 
   before_action :ensure_tags_enabled
-  before_action :ensure_visible, only: %i[show info]
 
   def self.show_methods
     Discourse.anonymous_filters.map { |f| :"show_#{f}" }
   end
 
+  before_action :ensure_visible, only: [:show, :info, *show_methods]
+
   requires_login except: [:index, :show, :tag_feed, :search, :info, *show_methods]
 
   skip_before_action :check_xhr, only: [:tag_feed, :show, :index, *show_methods]

programming_language: Ruby
filename: tags_controller_spec.rb
change_type: ModificationType.MODIFY
diff: @@ -676,6 +676,18 @@ RSpec.describe TagsController do
           expect(response.status).to eq(200)
         end
 
+        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
+
         context "with muted tags" do
           before do
             TagUser.create!(
@@ -755,6 +767,18 @@ RSpec.describe TagsController do
       get "/tag/#{tag.name}/l/top.json?period=decadely"
       expect(response.status).to eq(400)
     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
   end
 
   describe "#search" do

programming_language: Ruby