CVE-2024-24817: Insufficient Information (NVD-CWE-noinfo)
value: Discourse Calendar adds the ability to create a dynamic calendar in the first post of a topic on the open-source discussion platform Discourse. Prior to version 0.4, event invitees created in topics in private categories or PMs (private messages) can be retrieved by anyone, even if they're not logged in. This problem is resolved in version 0.4 of the discourse-calendar plugin. While no known workaround is available, putting the site behind `login_required` will disallow this endpoint to be used by anonymous users, but logged in users can still get the list of invitees in the private topics.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-02-22T18:15Z
Repository: https://github.com/discourse/discourse-calendar
Language: Ruby
Files changed: app/controllers/discourse_post_event/invitees_controller.rb, plugin.rb, spec/requests/invitees_controller_spec.rb
Commit date: 2024-02-22 11:32:47 +0800
Commit message: SECURITY: Hide invitees from users who are not allowed to see the event post (#544)


Diff: diff --git a/app/controllers/discourse_post_event/invitees_controller.rb b/app/controllers/discourse_post_event/invitees_controller.rb
index 39b636bf..59266b6e 100644
--- a/app/controllers/discourse_post_event/invitees_controller.rb
+++ b/app/controllers/discourse_post_event/invitees_controller.rb
@@ -2,10 +2,11 @@
 
 module DiscoursePostEvent
   class InviteesController < DiscoursePostEventController
     def index
       event = Event.find(params[:post_id])
+      guardian.ensure_can_see!(event.post)
 
       event_invitees = event.invitees
 
       if params[:filter]
         event_invitees =
diff --git a/plugin.rb b/plugin.rb
index b5ef5a78..339e124d 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -1,11 +1,11 @@
 # frozen_string_literal: true
 
 # name: discourse-calendar
 # about: Adds the ability to create a dynamic calendar with events in a topic.
 # meta_topic_id: 97376
-# version: 0.3
+# version: 0.4
 # author: Daniel Waterworth, Joffrey Jaffeux
 # url: https://github.com/discourse/discourse-calendar
 
 libdir = File.join(File.dirname(__FILE__), "vendor/holidays/lib")
 $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
diff --git a/spec/requests/invitees_controller_spec.rb b/spec/requests/invitees_controller_spec.rb
index d805b82f..1593fed0 100644
--- a/spec/requests/invitees_controller_spec.rb
+++ b/spec/requests/invitees_controller_spec.rb
@@ -13,10 +13,36 @@ module DiscoursePostEvent
     let(:user) { Fabricate(:user, admin: true) }
     let(:topic_1) { Fabricate(:topic, user: user) }
     let(:post_1) { Fabricate(:post, user: user, topic: topic_1) }
 
     describe "#index" do
+      context "for a post in a private category" do
+        let(:outside_user) { Fabricate(:user) }
+        let(:in_group_user) { Fabricate(:user) }
+        let(:group) { Fabricate(:group, users: [in_group_user]) }
+        let(:private_category) { Fabricate(:private_category, group:) }
+        let(:topic_1) { Fabricate(:topic, user: user, category: private_category) }
+        let(:post_1) { Fabricate(:post, user: user, topic: topic_1) }
+        let(:post_event_1) { Fabricate(:event, post: post_1) }
+
+        it "forbids non group user from seeing the list of invitees" do
+          sign_in(outside_user)
+
+          get "/discourse-post-event/events/#{post_event_1.id}/invitees.json"
+
+          expect(response.status).to eq(403)
+        end
+
+        it "allows group user to see the list of invitees" do
+          sign_in(in_group_user)
+
+          get "/discourse-post-event/events/#{post_event_1.id}/invitees.json"
+
+          expect(response.status).to eq(200)
+        end
+      end
+
       context "when params are included" do
         let(:invitee1) { Fabricate(:user, username: "Francis", name: "Francis") }
         let(:invitee2) { Fabricate(:user, username: "Francisco", name: "Francisco") }
         let(:invitee3) { Fabricate(:user, username: "Frank", name: "Frank") }
         let(:invitee4) { Fabricate(:user, username: "Franchesca", name: "Franchesca") }

Vulnerable code: # version: 0.3
Fixed code:       guardian.ensure_can_see!(event.post)
# version: 0.4
      context "for a post in a private category" do
        let(:outside_user) { Fabricate(:user) }
        let(:in_group_user) { Fabricate(:user) }
        let(:group) { Fabricate(:group, users: [in_group_user]) }
        let(:private_category) { Fabricate(:private_category, group:) }
        let(:topic_1) { Fabricate(:topic, user: user, category: private_category) }
        let(:post_1) { Fabricate(:post, user: user, topic: topic_1) }
        let(:post_event_1) { Fabricate(:event, post: post_1) }

        it "forbids non group user from seeing the list of invitees" do
          sign_in(outside_user)

          get "/discourse-post-event/events/#{post_event_1.id}/invitees.json"

          expect(response.status).to eq(403)
        end

        it "allows group user to see the list of invitees" do
          sign_in(in_group_user)

          get "/discourse-post-event/events/#{post_event_1.id}/invitees.json"

          expect(response.status).to eq(200)
        end
      end