Commit 53661b10 authored by GitLab Release Tools Bot's avatar GitLab Release Tools Bot

Merge branch 'security-hide_merge_request_ids_on_emails' into 'master'

Prevent disclosure of merge request id via email

See merge request gitlab/gitlabhq!3313
parents fac22c13 fb931424
...@@ -90,6 +90,8 @@ module EmailsHelper ...@@ -90,6 +90,8 @@ module EmailsHelper
when MergeRequest when MergeRequest
merge_request = MergeRequest.find(closed_via[:id]).present merge_request = MergeRequest.find(closed_via[:id]).present
return "" unless Ability.allowed?(@recipient, :read_merge_request, merge_request)
case format case format
when :html when :html
merge_request_link = link_to(merge_request.to_reference, merge_request.web_url) merge_request_link = link_to(merge_request.to_reference, merge_request.web_url)
...@@ -102,6 +104,8 @@ module EmailsHelper ...@@ -102,6 +104,8 @@ module EmailsHelper
# Technically speaking this should be Commit but per # Technically speaking this should be Commit but per
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15610#note_163812339 # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15610#note_163812339
# we can't deserialize Commit without custom serializer for ActiveJob # we can't deserialize Commit without custom serializer for ActiveJob
return "" unless Ability.allowed?(@recipient, :download_code, @project)
_("via %{closed_via}") % { closed_via: closed_via } _("via %{closed_via}") % { closed_via: closed_via }
else else
"" ""
......
...@@ -34,6 +34,8 @@ module Emails ...@@ -34,6 +34,8 @@ module Emails
setup_issue_mail(issue_id, recipient_id, closed_via: closed_via) setup_issue_mail(issue_id, recipient_id, closed_via: closed_via)
@updated_by = User.find(updated_by_user_id) @updated_by = User.find(updated_by_user_id)
@recipient = User.find(recipient_id)
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason)) mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
end end
......
---
title: Prevent disclosure of merge request ID via email
merge_request:
author:
type: security
...@@ -6,33 +6,65 @@ describe EmailsHelper do ...@@ -6,33 +6,65 @@ describe EmailsHelper do
let(:merge_request) { create(:merge_request) } let(:merge_request) { create(:merge_request) }
let(:merge_request_presenter) { merge_request.present } let(:merge_request_presenter) { merge_request.present }
context 'when user can read merge request' do
let(:user) { create(:user) }
before do
merge_request.project.add_developer(user)
self.instance_variable_set(:@recipient, user)
self.instance_variable_set(:@project, merge_request.project)
end
context "and format is text" do context "and format is text" do
it "returns plain text" do it "returns plain text" do
expect(closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})") expect(helper.closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
end end
end end
context "and format is HTML" do context "and format is HTML" do
it "returns HTML" do it "returns HTML" do
expect(closure_reason_text(merge_request, format: :html)).to eq("via merge request #{link_to(merge_request.to_reference, merge_request_presenter.web_url)}") expect(helper.closure_reason_text(merge_request, format: :html)).to eq("via merge request #{link_to(merge_request.to_reference, merge_request_presenter.web_url)}")
end end
end end
context "and format is unknown" do context "and format is unknown" do
it "returns plain text" do it "returns plain text" do
expect(closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})") expect(helper.closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
end
end
end
context 'when user cannot read merge request' do
it "does not have link to merge request" do
expect(helper.closure_reason_text(merge_request)).to be_empty
end end
end end
end end
context 'when given a String' do context 'when given a String' do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:closed_via) { "5a0eb6fd7e0f133044378c662fcbbc0d0c16dbfa" } let(:closed_via) { "5a0eb6fd7e0f133044378c662fcbbc0d0c16dbfa" }
context 'when user can read commits' do
before do
project.add_developer(user)
self.instance_variable_set(:@recipient, user)
self.instance_variable_set(:@project, project)
end
it "returns plain text" do it "returns plain text" do
expect(closure_reason_text(closed_via)).to eq("via #{closed_via}") expect(closure_reason_text(closed_via)).to eq("via #{closed_via}")
end end
end end
context 'when user cannot read commits' do
it "returns plain text" do
expect(closure_reason_text(closed_via)).to be_empty
end
end
end
context 'when not given anything' do context 'when not given anything' do
it "returns empty string" do it "returns empty string" do
expect(closure_reason_text(nil)).to eq("") expect(closure_reason_text(nil)).to eq("")
......
...@@ -60,35 +60,63 @@ describe Issues::CloseService do ...@@ -60,35 +60,63 @@ describe Issues::CloseService do
describe '#close_issue' do describe '#close_issue' do
context "closed by a merge request" do context "closed by a merge request" do
before do it 'mentions closure via a merge request' do
perform_enqueued_jobs do perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request) described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request)
end end
end
it 'mentions closure via a merge request' do
email = ActionMailer::Base.deliveries.last email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email) expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(issue.title) expect(email.subject).to include(issue.title)
expect(email.body.parts.map(&:body)).to all(include(closing_merge_request.to_reference)) expect(email.body.parts.map(&:body)).to all(include(closing_merge_request.to_reference))
end end
context 'when user cannot read merge request' do
it 'does not mention merge request' do
project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request)
end
email = ActionMailer::Base.deliveries.last
body_text = email.body.parts.map(&:body).join(" ")
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(issue.title)
expect(body_text).not_to include(closing_merge_request.to_reference)
end
end
end end
context "closed by a commit" do context "closed by a commit" do
before do it 'mentions closure via a commit' do
perform_enqueued_jobs do perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue, closed_via: closing_commit) described_class.new(project, user).close_issue(issue, closed_via: closing_commit)
end end
end
it 'mentions closure via a commit' do
email = ActionMailer::Base.deliveries.last email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email) expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(issue.title) expect(email.subject).to include(issue.title)
expect(email.body.parts.map(&:body)).to all(include(closing_commit.id)) expect(email.body.parts.map(&:body)).to all(include(closing_commit.id))
end end
context 'when user cannot read the commit' do
it 'does not mention the commit id' do
project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue, closed_via: closing_commit)
end
email = ActionMailer::Base.deliveries.last
body_text = email.body.parts.map(&:body).join(" ")
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(issue.title)
expect(body_text).not_to include(closing_commit.id)
end
end
end end
context "valid params" do context "valid params" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment