CVE-2022-0574: Incorrect Authorization (CWE-863)
value: Improper Access Control in GitHub repository publify/publify prior to 9.2.8.
CWE description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
CVSS v3 base score: 6.5
Published: 2022-05-16T15:15Z
Repository: https://github.com/publify/publify
Language: Ruby
Files changed: publify_core/app/models/article.rb, publify_core/spec/controllers/comments_controller_spec.rb, publify_core/spec/models/article_spec.rb
Commit date: 2022-02-13 16:40:55 +0100
Commit message: Do not allow comments on Article if not published

Diff: diff --git a/publify_core/app/models/article.rb b/publify_core/app/models/article.rb
index 548d959657..2bef0b2238 100644
--- a/publify_core/app/models/article.rb
+++ b/publify_core/app/models/article.rb
@@ -202,11 +202,11 @@ class Article < Content
   def notify_user_via_email(user)
     EmailNotify.send_article(self, user) if user.notify_via_email?
   end
 
   def comments_closed?
-    !(allow_comments? && in_feedback_window?)
+    !(allow_comments? && published? && in_feedback_window?)
   end
 
   def html_urls
     urls = []
     html.gsub(/<a\s+[^>]*>/) do |tag|
diff --git a/publify_core/spec/controllers/comments_controller_spec.rb b/publify_core/spec/controllers/comments_controller_spec.rb
index f53178f418..dd926ea97f 100644
--- a/publify_core/spec/controllers/comments_controller_spec.rb
+++ b/publify_core/spec/controllers/comments_controller_spec.rb
@@ -56,10 +56,25 @@ RSpec.describe CommentsController, type: :controller do
       aggregate_failures do
         expect(response).to render_template("articles/comment")
         expect(response.body).to have_text "content"
       end
     end
+
+    it "does not allow commenting if article does not allow comments" do
+      no_comments = create(:article, allow_comments: false)
+      expect do
+        post :create, xhr: true, params: { comment: comment_params,
+                                           article_id: no_comments.id }
+      end.not_to change(no_comments.comments, :count)
+    end
+
+    it "does not allow commenting if article is draft" do
+      draft = create(:article, state: "draft")
+      expect do
+        post :create, xhr: true, params: { comment: comment_params, article_id: draft.id }
+      end.not_to change(draft.comments, :count)
+    end
   end
 
   describe "#preview" do
     context "when using xhr post" do
       before do
diff --git a/publify_core/spec/models/article_spec.rb b/publify_core/spec/models/article_spec.rb
index 0357748eb8..b400f4140f 100644
--- a/publify_core/spec/models/article_spec.rb
+++ b/publify_core/spec/models/article_spec.rb
@@ -854,12 +854,13 @@ describe Article, type: :model do
     end
 
     it "returns only published articles" do
       article = create(:article)
       create(:comment, article: article)
-      unpublished_article = create(:article, state: "draft")
+      unpublished_article = create(:article)
       create(:comment, article: unpublished_article)
+      unpublished_article.update!(state: "draft")
       expect(described_class.published).to eq([article])
       expect(described_class.bestof).to eq([article])
     end
 
     it "returns article sorted by comment counts" do
@@ -953,10 +954,21 @@ describe Article, type: :model do
     end
 
     context "when auto_close setting is zero" do
       let(:auto_close_value) { 0 }
 
+      it "does not allow comments for a draft article" do
+        art = build :article, state: "draft", blog: blog
+        assert art.comments_closed?
+      end
+
+      it "does not allow comments for an article that will be published in the future" do
+        art = build :article, state: "publication_pending",
+                              published_at: 1.day.from_now, blog: blog
+        assert art.comments_closed?
+      end
+
       it "allows comments for a newly published article" do
         art = build :article, published_at: 1.second.ago, blog: blog
         assert !art.comments_closed?
       end
 

Vulnerable code:     !(allow_comments? && in_feedback_window?)
      unpublished_article = create(:article, state: "draft")
Fixed code:     !(allow_comments? && published? && in_feedback_window?)

    it "does not allow commenting if article does not allow comments" do
      no_comments = create(:article, allow_comments: false)
      expect do
        post :create, xhr: true, params: { comment: comment_params,
                                           article_id: no_comments.id }
      end.not_to change(no_comments.comments, :count)
    end

    it "does not allow commenting if article is draft" do
      draft = create(:article, state: "draft")
      expect do
        post :create, xhr: true, params: { comment: comment_params, article_id: draft.id }
      end.not_to change(draft.comments, :count)
    end
      unpublished_article = create(:article)
      unpublished_article.update!(state: "draft")
      it "does not allow comments for a draft article" do
        art = build :article, state: "draft", blog: blog
        assert art.comments_closed?
      end

      it "does not allow comments for an article that will be published in the future" do
        art = build :article, state: "publication_pending",
                              published_at: 1.day.from_now, blog: blog
        assert art.comments_closed?
      end