From 1c42f748f8cac88692d3dca5470f74331e48b8d1 Mon Sep 17 00:00:00 2001 From: Fabio Pitino Date: Fri, 21 Jun 2019 17:56:03 +0100 Subject: [PATCH] Don't display badges when builds are restricted Badges were leaked to unauthorized users even when Public Builds project setting is disabled. Added guard clause to the controller to check if user can read build. --- app/controllers/projects/badges_controller.rb | 3 +- ...ix-badges-leaked-to-unauthorized-users.yml | 5 + .../projects/badges_controller_spec.rb | 128 +++++++++++++----- 3 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 changelogs/unreleased/security-fix-badges-leaked-to-unauthorized-users.yml diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index 09a384e89ab..66b51b17790 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -3,7 +3,8 @@ class Projects::BadgesController < Projects::ApplicationController layout 'project_settings' before_action :authorize_admin_project!, only: [:index] - before_action :no_cache_headers, except: [:index] + before_action :no_cache_headers, only: [:pipeline, :coverage] + before_action :authorize_read_build!, only: [:pipeline, :coverage] def pipeline pipeline_status = Gitlab::Badge::Pipeline::Status diff --git a/changelogs/unreleased/security-fix-badges-leaked-to-unauthorized-users.yml b/changelogs/unreleased/security-fix-badges-leaked-to-unauthorized-users.yml new file mode 100644 index 00000000000..9526f3c559f --- /dev/null +++ b/changelogs/unreleased/security-fix-badges-leaked-to-unauthorized-users.yml @@ -0,0 +1,5 @@ +--- +title: Show badges if pipelines are public otherwise default to project permissions. +erge_request: +author: +type: security diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb index 5ec8d8d41d7..4ae29ba7f54 100644 --- a/spec/controllers/projects/badges_controller_spec.rb +++ b/spec/controllers/projects/badges_controller_spec.rb @@ -7,51 +7,115 @@ describe Projects::BadgesController do let!(:pipeline) { create(:ci_empty_pipeline) } let(:user) { create(:user) } - before do - project.add_maintainer(user) - sign_in(user) - end + shared_examples 'a badge resource' do |badge_type| + context 'when pipelines are public' do + before do + project.update!(public_builds: true) + end - it 'requests the pipeline badge successfully' do - get_badge(:pipeline) + context 'when project is public' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end - expect(response).to have_gitlab_http_status(:ok) - end + it "returns the #{badge_type} badge to unauthenticated users" do + get_badge(badge_type) - it 'requests the coverage badge successfully' do - get_badge(:coverage) + expect(response).to have_gitlab_http_status(:ok) + end + end - expect(response).to have_gitlab_http_status(:ok) - end + context 'when project is restricted' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) + project.add_guest(user) + sign_in(user) + end - it 'renders the `flat` badge layout by default' do - get_badge(:coverage) + it "returns the #{badge_type} badge to guest users" do + get_badge(badge_type) - expect(response).to render_template('projects/badges/badge') - end + expect(response).to have_gitlab_http_status(:ok) + end + end + end - context 'when style param is set to `flat`' do - it 'renders the `flat` badge layout' do - get_badge(:coverage, 'flat') + context 'format' do + before do + project.add_maintainer(user) + sign_in(user) + end - expect(response).to render_template('projects/badges/badge') + it 'renders the `flat` badge layout by default' do + get_badge(badge_type) + + expect(response).to render_template('projects/badges/badge') + end + + context 'when style param is set to `flat`' do + it 'renders the `flat` badge layout' do + get_badge(badge_type, 'flat') + + expect(response).to render_template('projects/badges/badge') + end + end + + context 'when style param is set to an invalid type' do + it 'renders the `flat` (default) badge layout' do + get_badge(badge_type, 'xxx') + + expect(response).to render_template('projects/badges/badge') + end + end + + context 'when style param is set to `flat-square`' do + it 'renders the `flat-square` badge layout' do + get_badge(badge_type, 'flat-square') + + expect(response).to render_template('projects/badges/badge_flat-square') + end + end + end + + context 'when pipelines are not public' do + before do + project.update!(public_builds: false) + end + + context 'when project is public' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end + + it 'returns 404 to unauthenticated users' do + get_badge(badge_type) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when project is restricted to the user' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) + project.add_guest(user) + sign_in(user) + end + + it 'defaults to project permissions' do + get_badge(:coverage) + + expect(response).to have_gitlab_http_status(:not_found) + end + end end end - context 'when style param is set to an invalid type' do - it 'renders the `flat` (default) badge layout' do - get_badge(:coverage, 'xxx') - - expect(response).to render_template('projects/badges/badge') - end + describe '#pipeline' do + it_behaves_like 'a badge resource', :pipeline end - context 'when style param is set to `flat-square`' do - it 'renders the `flat-square` badge layout' do - get_badge(:coverage, 'flat-square') - - expect(response).to render_template('projects/badges/badge_flat-square') - end + describe '#coverage' do + it_behaves_like 'a badge resource', :coverage end def get_badge(badge, style = nil)