FIX: throw error when link in reason for grant badge is an external link (#6690)

FIX: throw error when link in reason for grant badge is an external link (#6690)

From 55945ec7c8f975d1ac3e1695b0d8779b28823cfa Mon Sep 17 00:00:00 2001
From: Saurabh Patel <saurabh.finch@gmail.com>
Date: Wed, 28 Nov 2018 22:31:41 +0530
Subject: [PATCH] FIX: throw error when link in reason for grant badge is an
 external link (#6690)


diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb
index 33bafc5..c830798 100644
--- a/app/controllers/user_badges_controller.rb
+++ b/app/controllers/user_badges_controller.rb
@@ -50,14 +50,17 @@ class UserBadgesController < ApplicationController
     user = fetch_user_from_params
 
     unless can_assign_badge_to_user?(user)
-      render json: failed_json, status: 403
-      return
+      return render json: failed_json, status: 403
     end
 
     badge = fetch_badge_from_params
     post_id = nil
 
     if params[:reason].present?
+      unless is_badge_reason_valid? params[:reason]
+        return render json: { failed: I18n.t('invalid_grant_badge_reason_link') }, status: 400
+      end
+
       path = begin
         URI.parse(params[:reason]).path
       rescue URI::Error
@@ -116,4 +119,9 @@ class UserBadgesController < ApplicationController
   def ensure_badges_enabled
     raise Discourse::NotFound unless SiteSetting.enable_badges?
   end
+
+  def is_badge_reason_valid?(reason)
+    route = Discourse.route_for(reason)
+    route && (route[:controller] == 'posts' || route[:controller] == 'topics')
+  end
 end
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 048273b..9d61367 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -210,6 +210,7 @@ en:
   provider_not_enabled: "You are not permitted to view the requested resource. The authentication provider is not enabled."
   provider_not_found: "You are not permitted to view the requested resource. The authentication provider does not exist."
   read_only_mode_enabled: "The site is in read only mode. Interactions are disabled."
+  invalid_grant_badge_reason_link: "External or invalid discourse link is not allowed in badge reason"
 
   reading_time: "Reading time"
   likes: "Likes"
diff --git a/spec/requests/user_badges_controller_spec.rb b/spec/requests/user_badges_controller_spec.rb
index ae8199d..92da1a6 100644
--- a/spec/requests/user_badges_controller_spec.rb
+++ b/spec/requests/user_badges_controller_spec.rb
@@ -143,6 +143,51 @@ describe UserBadgesController do
 
       expect(events).to include(:user_badge_granted)
     end
+
+    it 'does not grant badge when external link is used in reason' do
+      admin = Fabricate(:admin)
+      post = create_post
+
+      sign_in(admin)
+
+      post "/user_badges.json", params: {
+        badge_id: badge.id,
+        username: user.username,
+        reason: "http://example.com/" + post.url
+      }
+
+      expect(response.status).to eq(400)
+    end
+
+    it 'does not grant badge if invalid discourse post/topic link is used in reason' do
+      admin = Fabricate(:admin)
+      post = create_post
+
+      sign_in(admin)
+
+      post "/user_badges.json", params: {
+        badge_id: badge.id,
+        username: user.username,
+        reason: Discourse.base_url + "/random_url/" + post.url
+      }
+
+      expect(response.status).to eq(400)
+    end
+
+    it 'grants badge when valid post/topic link is given in reason' do
+      admin = Fabricate(:admin)
+      post = create_post
+
+      sign_in(admin)
+
+      post "/user_badges.json", params: {
+        badge_id: badge.id,
+        username: user.username,
+        reason: Discourse.base_url + post.url
+      }
+
+      expect(response.status).to eq(200)
+    end
   end
 
   context 'destroy' do

GitHub

1 Like