Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/project_services/slash_commands_service.rb2
-rw-r--r--app/policies/global_policy.rb3
-rw-r--r--app/serializers/issue_entity.rb7
-rw-r--r--app/services/merge_requests/build_service.rb28
-rw-r--r--changelogs/unreleased/security-2873-blocked-user-slash-command-bypass-master.yml5
-rw-r--r--changelogs/unreleased/security-bvl-filter-mr-params.yml5
-rw-r--r--changelogs/unreleased/security-hide_moved_issue_id.yml5
-rw-r--r--spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb (renamed from spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb)21
-rw-r--r--spec/policies/global_policy_spec.rb28
-rw-r--r--spec/serializers/issue_entity_spec.rb33
-rw-r--r--spec/services/merge_requests/build_service_spec.rb37
-rw-r--r--spec/support/shared_examples/chat_slash_commands_shared_examples.rb13
-rw-r--r--spec/uploaders/file_mover_spec.rb3
13 files changed, 179 insertions, 11 deletions
diff --git a/app/models/project_services/slash_commands_service.rb b/app/models/project_services/slash_commands_service.rb
index bfabc6d262c..46925f6704d 100644
--- a/app/models/project_services/slash_commands_service.rb
+++ b/app/models/project_services/slash_commands_service.rb
@@ -35,6 +35,8 @@ class SlashCommandsService < Service
chat_user = find_chat_user(params)
if chat_user&.user
+ return Gitlab::SlashCommands::Presenters::Access.new.access_denied unless chat_user.user.can?(:use_slash_commands)
+
Gitlab::SlashCommands::Command.new(project, chat_user, params).execute
else
url = authorize_chat_name_url(params)
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index e85397422e6..1807b741edb 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -37,6 +37,7 @@ class GlobalPolicy < BasePolicy
enable :access_git
enable :receive_notifications
enable :use_quick_actions
+ enable :use_slash_commands
end
rule { blocked | internal }.policy do
@@ -44,6 +45,7 @@ class GlobalPolicy < BasePolicy
prevent :access_api
prevent :access_git
prevent :receive_notifications
+ prevent :use_slash_commands
end
rule { required_terms_not_accepted }.policy do
@@ -61,6 +63,7 @@ class GlobalPolicy < BasePolicy
rule { access_locked }.policy do
prevent :log_in
+ prevent :use_slash_commands
end
rule { ~(anonymous & restricted_public_level) }.policy do
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 914ad628a99..2e994f4c3f1 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -16,9 +16,14 @@ class IssueEntity < IssuableEntity
expose :discussion_locked
expose :assignees, using: API::Entities::UserBasic
expose :due_date
- expose :moved_to_id
expose :project_id
+ expose :moved_to_id do |issue|
+ if issue.moved_to_id.present? && can?(request.current_user, :read_issue, issue.moved_to)
+ issue.moved_to_id
+ end
+ end
+
expose :web_url do |issue|
project_issue_path(issue.project, issue)
end
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 109c964e577..b28f80939ae 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -11,15 +11,18 @@ module MergeRequests
# https://gitlab.com/gitlab-org/gitlab-ce/issues/53658
merge_quick_actions_into_params!(merge_request, only: [:target_branch])
merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) if params.has_key?(:force_remove_source_branch)
- merge_request.assign_attributes(params)
+ # Assign the projects first so we can use policies for `filter_params`
merge_request.author = current_user
+ merge_request.source_project = find_source_project
+ merge_request.target_project = find_target_project
+
+ filter_params(merge_request)
+ merge_request.assign_attributes(params.to_h.compact)
+
merge_request.compare_commits = []
- merge_request.source_project = find_source_project
- merge_request.target_project = find_target_project
- merge_request.target_branch = find_target_branch
- merge_request.can_be_created = projects_and_branches_valid?
- ensure_milestone_available(merge_request)
+ merge_request.target_branch = find_target_branch
+ merge_request.can_be_created = projects_and_branches_valid?
# compare branches only if branches are valid, otherwise
# compare_branches may raise an error
@@ -50,12 +53,14 @@ module MergeRequests
to: :merge_request
def find_source_project
+ source_project = project_from_params(:source_project)
return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
project
end
def find_target_project
+ target_project = project_from_params(:target_project)
return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
target_project = project.default_merge_request_target
@@ -65,6 +70,17 @@ module MergeRequests
project
end
+ def project_from_params(param_name)
+ project_from_params = params.delete(param_name)
+
+ id_param_name = :"#{param_name}_id"
+ if project_from_params.nil? && params[id_param_name]
+ project_from_params = Project.find_by_id(params.delete(id_param_name))
+ end
+
+ project_from_params
+ end
+
def find_target_branch
target_branch || target_project.default_branch
end
diff --git a/changelogs/unreleased/security-2873-blocked-user-slash-command-bypass-master.yml b/changelogs/unreleased/security-2873-blocked-user-slash-command-bypass-master.yml
new file mode 100644
index 00000000000..cd31fe0f35c
--- /dev/null
+++ b/changelogs/unreleased/security-2873-blocked-user-slash-command-bypass-master.yml
@@ -0,0 +1,5 @@
+---
+title: Restrict slash commands to users who can log in
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-bvl-filter-mr-params.yml b/changelogs/unreleased/security-bvl-filter-mr-params.yml
new file mode 100644
index 00000000000..4433ec73b7c
--- /dev/null
+++ b/changelogs/unreleased/security-bvl-filter-mr-params.yml
@@ -0,0 +1,5 @@
+---
+title: Filter merge request params on the new merge request page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-hide_moved_issue_id.yml b/changelogs/unreleased/security-hide_moved_issue_id.yml
new file mode 100644
index 00000000000..24353d797c9
--- /dev/null
+++ b/changelogs/unreleased/security-hide_moved_issue_id.yml
@@ -0,0 +1,5 @@
+---
+title: Do not show moved issue id for users that cannot read issue
+merge_request:
+author:
+type: security
diff --git a/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb b/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb
index 9318b5f1ebb..1ebe9e2e409 100644
--- a/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb
+++ b/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
require 'spec_helper'
-describe 'Merge Request > Tries to access private repo of public project' do
+describe 'Merge Request > User tries to access private project information through the new mr page' do
let(:current_user) { create(:user) }
let(:private_project) do
create(:project, :public, :repository,
@@ -33,5 +35,22 @@ describe 'Merge Request > Tries to access private repo of public project' do
it "does not mention the project the user can't see the repo of" do
expect(page).not_to have_content('nothing-to-see-here')
end
+
+ context 'when the user enters label information from the private project in the querystring' do
+ let(:inaccessible_label) { create(:label, project: private_project) }
+ let(:mr_path) do
+ project_new_merge_request_path(
+ owned_project,
+ merge_request: {
+ label_ids: [inaccessible_label.id],
+ source_branch: 'feature'
+ }
+ )
+ end
+
+ it 'does not expose the label name' do
+ expect(page).not_to have_content(inaccessible_label.name)
+ end
+ end
end
end
diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb
index 12be3927e18..df6cc526eb0 100644
--- a/spec/policies/global_policy_spec.rb
+++ b/spec/policies/global_policy_spec.rb
@@ -226,4 +226,32 @@ describe GlobalPolicy do
it { is_expected.not_to be_allowed(:read_instance_statistics) }
end
end
+
+ describe 'slash commands' do
+ context 'regular user' do
+ it { is_expected.to be_allowed(:use_slash_commands) }
+ end
+
+ context 'when internal' do
+ let(:current_user) { User.ghost }
+
+ it { is_expected.not_to be_allowed(:use_slash_commands) }
+ end
+
+ context 'when blocked' do
+ before do
+ current_user.block
+ end
+
+ it { is_expected.not_to be_allowed(:use_slash_commands) }
+ end
+
+ context 'when access locked' do
+ before do
+ current_user.lock_access!
+ end
+
+ it { is_expected.not_to be_allowed(:use_slash_commands) }
+ end
+ end
end
diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb
index caa3e41402b..0e05b3c84f4 100644
--- a/spec/serializers/issue_entity_spec.rb
+++ b/spec/serializers/issue_entity_spec.rb
@@ -17,4 +17,37 @@ describe IssueEntity do
it 'has time estimation attributes' do
expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent)
end
+
+ context 'when issue got moved' do
+ let(:public_project) { create(:project, :public) }
+ let(:member) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:issue) { create(:issue, project: public_project) }
+
+ before do
+ project.add_developer(member)
+ public_project.add_developer(member)
+ Issues::MoveService.new(public_project, member).execute(issue, project)
+ end
+
+ context 'when user cannot read target project' do
+ it 'does not return moved_to_id' do
+ request = double('request', current_user: non_member)
+
+ response = described_class.new(issue, request: request).as_json
+
+ expect(response[:moved_to_id]).to be_nil
+ end
+ end
+
+ context 'when user can read target project' do
+ it 'returns moved moved_to_id' do
+ request = double('request', current_user: member)
+
+ response = described_class.new(issue, request: request).as_json
+
+ expect(response[:moved_to_id]).to eq(issue.moved_to_id)
+ end
+ end
+ end
end
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 5c3b209086c..f18239f6d39 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe MergeRequests::BuildService do
@@ -225,6 +224,11 @@ describe MergeRequests::BuildService do
let(:label_ids) { [label2.id] }
let(:milestone_id) { milestone2.id }
+ before do
+ # Guests are not able to assign labels or milestones to an issue
+ project.add_developer(user)
+ end
+
it 'assigns milestone_id and label_ids instead of issue labels and milestone' do
expect(merge_request.milestone).to eq(milestone2)
expect(merge_request.labels).to match_array([label2])
@@ -479,4 +483,35 @@ describe MergeRequests::BuildService do
end
end
end
+
+ context 'when assigning labels' do
+ let(:label_ids) { [create(:label, project: project).id] }
+
+ context 'for members with less than developer access' do
+ it 'is not allowed' do
+ expect(merge_request.label_ids).to be_empty
+ end
+ end
+
+ context 'for users allowed to assign labels' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'for labels in the project' do
+ it 'is allowed for developers' do
+ expect(merge_request.label_ids).to contain_exactly(*label_ids)
+ end
+ end
+
+ context 'for unrelated labels' do
+ let(:project_label) { create(:label, project: project) }
+ let(:label_ids) { [create(:label).id, project_label.id] }
+
+ it 'only assigns related labels' do
+ expect(merge_request.label_ids).to contain_exactly(project_label.id)
+ end
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/chat_slash_commands_shared_examples.rb b/spec/support/shared_examples/chat_slash_commands_shared_examples.rb
index dc97a39f051..ef40287fd6e 100644
--- a/spec/support/shared_examples/chat_slash_commands_shared_examples.rb
+++ b/spec/support/shared_examples/chat_slash_commands_shared_examples.rb
@@ -91,6 +91,19 @@ RSpec.shared_examples 'chat slash commands service' do
subject.trigger(params)
end
+
+ context 'when user is blocked' do
+ before do
+ chat_name.user.block
+ end
+
+ it 'blocks command execution' do
+ expect_any_instance_of(Gitlab::SlashCommands::Command).not_to receive(:execute)
+
+ result = subject.trigger(params)
+ expect(result).to include(text: /^Whoops! This action is not allowed/)
+ end
+ end
end
end
end
diff --git a/spec/uploaders/file_mover_spec.rb b/spec/uploaders/file_mover_spec.rb
index a9e03f3d4e5..5ee0a10f38d 100644
--- a/spec/uploaders/file_mover_spec.rb
+++ b/spec/uploaders/file_mover_spec.rb
@@ -85,8 +85,7 @@ describe FileMover do
context 'when tmp uploader is not local storage' do
before do
- allow(PersonalFileUploader).to receive(:object_store_enabled?) { true }
- tmp_uploader.object_store = ObjectStorage::Store::REMOTE
+ stub_uploads_object_storage(uploader: PersonalFileUploader)
allow_any_instance_of(PersonalFileUploader).to receive(:file_storage?) { false }
end