From 55945ec7c8f975d1ac3e1695b0d8779b28823cfa Mon Sep 17 00:00:00 2001 From: Saurabh Patel 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) --- app/controllers/user_badges_controller.rb | 12 +++++- config/locales/server.en.yml | 1 + spec/requests/user_badges_controller_spec.rb | 45 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb index 33bafc5241b..c830798867e 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 048273bef3f..9d613670f1b 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 ae8199dd8ea..92da1a693e0 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