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
path: root/spec/lib
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/banzai/filter/front_matter_filter_spec.rb32
-rw-r--r--spec/lib/banzai/filter/inline_diff_filter_spec.rb8
-rw-r--r--spec/lib/banzai/filter/math_filter_spec.rb8
-rw-r--r--spec/lib/bitbucket_server/representation/pull_request_spec.rb1
-rw-r--r--spec/lib/gitlab/background_migration/mailers/unconfirm_mailer_spec.rb2
-rw-r--r--spec/lib/gitlab/checks/tag_check_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/artifacts/decompressed_artifact_size_validator_spec.rb95
-rw-r--r--spec/lib/gitlab/ci/decompressed_gzip_size_validator_spec.rb127
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb12
9 files changed, 296 insertions, 14 deletions
diff --git a/spec/lib/banzai/filter/front_matter_filter_spec.rb b/spec/lib/banzai/filter/front_matter_filter_spec.rb
index b15f3ad2cd6..9d25dafb727 100644
--- a/spec/lib/banzai/filter/front_matter_filter_spec.rb
+++ b/spec/lib/banzai/filter/front_matter_filter_spec.rb
@@ -189,19 +189,29 @@ RSpec.describe Banzai::Filter::FrontMatterFilter, feature_category: :team_planni
end
end
- it 'fails fast for strings with many spaces' do
- content = "coding:" + " " * 50_000 + ";"
+ describe 'protects against malicious backtracking' do
+ it 'fails fast for strings with many spaces' do
+ content = "coding:" + " " * 50_000 + ";"
- expect do
- Timeout.timeout(3.seconds) { filter(content) }
- end.not_to raise_error
- end
+ expect do
+ Timeout.timeout(3.seconds) { filter(content) }
+ end.not_to raise_error
+ end
+
+ it 'fails fast for strings with many newlines' do
+ content = "coding:\n" + ";;;" + "\n" * 10_000 + "x"
- it 'fails fast for strings with many newlines' do
- content = "coding:\n" + ";;;" + "\n" * 10_000 + "x"
+ expect do
+ Timeout.timeout(3.seconds) { filter(content) }
+ end.not_to raise_error
+ end
+
+ it 'fails fast for strings with many `coding:`' do
+ content = "coding:" * 120_000 + "\n" * 80_000 + ";"
- expect do
- Timeout.timeout(3.seconds) { filter(content) }
- end.not_to raise_error
+ expect do
+ Timeout.timeout(3.seconds) { filter(content) }
+ end.not_to raise_error
+ end
end
end
diff --git a/spec/lib/banzai/filter/inline_diff_filter_spec.rb b/spec/lib/banzai/filter/inline_diff_filter_spec.rb
index 1ef00139db2..1388a9053d9 100644
--- a/spec/lib/banzai/filter/inline_diff_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_diff_filter_spec.rb
@@ -67,4 +67,12 @@ RSpec.describe Banzai::Filter::InlineDiffFilter do
doc = "<tt>START {+something added+} END</tt>"
expect(filter(doc).to_html).to eq(doc)
end
+
+ it 'protects against malicious backtracking' do
+ doc = '[-{-' * 250_000
+
+ expect do
+ Timeout.timeout(3.seconds) { filter(doc) }
+ end.not_to raise_error
+ end
end
diff --git a/spec/lib/banzai/filter/math_filter_spec.rb b/spec/lib/banzai/filter/math_filter_spec.rb
index 50784d3e423..f59529364c3 100644
--- a/spec/lib/banzai/filter/math_filter_spec.rb
+++ b/spec/lib/banzai/filter/math_filter_spec.rb
@@ -215,6 +215,14 @@ RSpec.describe Banzai::Filter::MathFilter, feature_category: :team_planning do
expect(doc.search('.js-render-math').count).to eq(2)
end
+ it 'protects against malicious backtracking' do
+ doc = pipeline_filter("$$#{' ' * 1_000_000}$")
+
+ expect do
+ Timeout.timeout(3.seconds) { filter(doc) }
+ end.not_to raise_error
+ end
+
def pipeline_filter(text)
context = { project: nil, no_sourcepos: true }
doc = Banzai::Pipeline::PreProcessPipeline.call(text, {})
diff --git a/spec/lib/bitbucket_server/representation/pull_request_spec.rb b/spec/lib/bitbucket_server/representation/pull_request_spec.rb
index c5d0ee8908d..5312bc1d71b 100644
--- a/spec/lib/bitbucket_server/representation/pull_request_spec.rb
+++ b/spec/lib/bitbucket_server/representation/pull_request_spec.rb
@@ -115,7 +115,6 @@ RSpec.describe BitbucketServer::Representation::PullRequest, feature_category: :
author: "root",
description: "Test",
source_branch_name: "refs/heads/root/CODE_OF_CONDUCTmd-1530600625006",
- source_branch_sha: "074e2b4dddc5b99df1bf9d4a3f66cfc15481fdc8",
target_branch_name: "refs/heads/master",
target_branch_sha: "839fa9a2d434eb697815b8fcafaecc51accfdbbc",
title: "Added a new line"
diff --git a/spec/lib/gitlab/background_migration/mailers/unconfirm_mailer_spec.rb b/spec/lib/gitlab/background_migration/mailers/unconfirm_mailer_spec.rb
index f430009989b..05bd020d4e2 100644
--- a/spec/lib/gitlab/background_migration/mailers/unconfirm_mailer_spec.rb
+++ b/spec/lib/gitlab/background_migration/mailers/unconfirm_mailer_spec.rb
@@ -7,6 +7,6 @@ RSpec.describe Gitlab::BackgroundMigration::Mailers::UnconfirmMailer do
let(:subject) { described_class.unconfirm_notification_email(user) }
it 'contains abuse report url' do
- expect(subject.body.encoded).to include(Rails.application.routes.url_helpers.new_abuse_report_url(user_id: user.id))
+ expect(subject.body.encoded).to include(Gitlab::Routing.url_helpers.user_url(user.id))
end
end
diff --git a/spec/lib/gitlab/checks/tag_check_spec.rb b/spec/lib/gitlab/checks/tag_check_spec.rb
index 50ffa5fad10..e75b0459337 100644
--- a/spec/lib/gitlab/checks/tag_check_spec.rb
+++ b/spec/lib/gitlab/checks/tag_check_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Checks::TagCheck do
+RSpec.describe Gitlab::Checks::TagCheck, feature_category: :source_code_management do
include_context 'change access checks context'
describe '#validate!' do
@@ -14,6 +14,29 @@ RSpec.describe Gitlab::Checks::TagCheck do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to change existing tags on this project.')
end
+ context "prohibited tags check" do
+ it "prohibits tag names that include refs/tags/ at the head" do
+ allow(subject).to receive(:tag_name).and_return("refs/tags/foo")
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a tag with a prohibited pattern.")
+ end
+
+ it "doesn't prohibit a nested refs/tags/ string in a tag name" do
+ allow(subject).to receive(:tag_name).and_return("fix-for-refs/tags/foo")
+
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ context "deleting a refs/tags headed tag" do
+ let(:newrev) { "0000000000000000000000000000000000000000" }
+ let(:ref) { "refs/tags/refs/tags/267208abfe40e546f5e847444276f7d43a39503e" }
+
+ it "doesn't prohibit the deletion of a refs/tags/ tag name" do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+
context 'with protected tag' do
let!(:protected_tag) { create(:protected_tag, project: project, name: 'v*') }
diff --git a/spec/lib/gitlab/ci/artifacts/decompressed_artifact_size_validator_spec.rb b/spec/lib/gitlab/ci/artifacts/decompressed_artifact_size_validator_spec.rb
new file mode 100644
index 00000000000..ef39a431d63
--- /dev/null
+++ b/spec/lib/gitlab/ci/artifacts/decompressed_artifact_size_validator_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Artifacts::DecompressedArtifactSizeValidator, feature_category: :build_artifacts do
+ include WorkhorseHelpers
+
+ let_it_be(:file_path) { File.join(Dir.tmpdir, 'decompressed_archive_size_validator_spec.gz') }
+ let(:file) { File.open(file_path) }
+ let(:file_format) { :gzip }
+ let(:max_bytes) { 20 }
+ let(:gzip_valid?) { true }
+ let(:validator) { instance_double(::Gitlab::Ci::DecompressedGzipSizeValidator, valid?: gzip_valid?) }
+
+ before(:all) do
+ Zlib::GzipWriter.open(file_path) do |gz|
+ gz.write('Hello World!')
+ end
+ end
+
+ after(:all) do
+ FileUtils.rm(file_path)
+ end
+
+ before do
+ allow(::Gitlab::Ci::DecompressedGzipSizeValidator)
+ .to receive(:new)
+ .and_return(validator)
+ end
+
+ subject { described_class.new(file: file, file_format: file_format, max_bytes: max_bytes) }
+
+ shared_examples 'when file does not exceed allowed compressed size' do
+ let(:gzip_valid?) { true }
+
+ it 'passes validation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+
+ shared_examples 'when file exceeds allowed decompressed size' do
+ let(:gzip_valid?) { false }
+
+ it 'raises an exception' do
+ expect { subject.validate! }
+ .to raise_error(Gitlab::Ci::Artifacts::DecompressedArtifactSizeValidator::FileDecompressionError)
+ end
+ end
+
+ describe '#validate!' do
+ it_behaves_like 'when file does not exceed allowed compressed size'
+
+ it_behaves_like 'when file exceeds allowed decompressed size'
+ end
+
+ context 'when file is not provided' do
+ let(:file) { nil }
+
+ it 'passes validation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+
+ context 'when the file is located in the cloud' do
+ let(:remote_path) { File.join(remote_store_path, remote_id) }
+
+ let(:file_url) { "http://s3.amazonaws.com/#{remote_path}" }
+ let(:file) do
+ instance_double(JobArtifactUploader,
+ path: file_path,
+ url: file_url,
+ object_store: ObjectStorage::Store::REMOTE)
+ end
+
+ let(:remote_id) { 'generated-remote-id-12345' }
+ let(:remote_store_path) { ObjectStorage::TMP_UPLOAD_PATH }
+
+ before do
+ stub_request(:get, %r{s3.amazonaws.com/#{remote_path}})
+ .to_return(status: 200, body: File.read('spec/fixtures/build.env.gz'))
+ end
+
+ it_behaves_like 'when file does not exceed allowed compressed size'
+
+ it_behaves_like 'when file exceeds allowed decompressed size'
+ end
+
+ context 'when file_format is not on the list' do
+ let_it_be(:file_format) { 'rar' }
+
+ it 'passes validation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/decompressed_gzip_size_validator_spec.rb b/spec/lib/gitlab/ci/decompressed_gzip_size_validator_spec.rb
new file mode 100644
index 00000000000..6ca3f4d415e
--- /dev/null
+++ b/spec/lib/gitlab/ci/decompressed_gzip_size_validator_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::DecompressedGzipSizeValidator, feature_category: :importers do
+ let_it_be(:filepath) { File.join(Dir.tmpdir, 'decompressed_gzip_size_validator_spec.gz') }
+
+ before(:all) do
+ create_compressed_file
+ end
+
+ after(:all) do
+ FileUtils.rm(filepath)
+ end
+
+ subject { described_class.new(archive_path: filepath, max_bytes: max_bytes) }
+
+ describe '#valid?' do
+ let(:max_bytes) { 20 }
+
+ context 'when file does not exceed allowed decompressed size' do
+ it 'returns true' do
+ expect(subject.valid?).to eq(true)
+ end
+
+ context 'when the waiter thread no longer exists due to being terminated or crashing' do
+ it 'gracefully handles the absence of the waiter without raising exception' do
+ allow(Process).to receive(:getpgid).and_raise(Errno::ESRCH)
+
+ expect(subject.valid?).to eq(true)
+ end
+ end
+ end
+
+ context 'when file exceeds allowed decompressed size' do
+ let(:max_bytes) { 1 }
+
+ it 'returns false' do
+ expect(subject.valid?).to eq(false)
+ end
+ end
+
+ context 'when exception occurs during header readings' do
+ shared_examples 'raises exception and terminates validator process group' do
+ let(:std) { instance_double(IO, close: nil) }
+ let(:wait_thr) { double }
+ let(:wait_threads) { [wait_thr, wait_thr] }
+
+ before do
+ allow(Process).to receive(:getpgid).and_return(2)
+ allow(Open3).to receive(:pipeline_r).and_return([std, wait_threads])
+ allow(wait_thr).to receive(:[]).with(:pid).and_return(1)
+ allow(wait_thr).to receive(:value).and_raise(exception)
+ end
+
+ it 'terminates validator process group' do
+ expect(Process).to receive(:kill).with(-1, 2).twice
+ expect(subject.valid?).to eq(false)
+ end
+ end
+
+ context 'when timeout occurs' do
+ let(:exception) { Timeout::Error }
+
+ include_examples 'raises exception and terminates validator process group'
+ end
+
+ context 'when exception occurs' do
+ let(:error_message) { 'Error!' }
+ let(:exception) { StandardError.new(error_message) }
+
+ include_examples 'raises exception and terminates validator process group'
+ end
+ end
+
+ describe 'archive path validation' do
+ let(:filesize) { nil }
+
+ context 'when archive path is traversed' do
+ let(:filepath) { '/foo/../bar' }
+
+ it 'does not pass validation' do
+ expect(subject.valid?).to eq(false)
+ end
+ end
+ end
+
+ context 'when archive path is not a string' do
+ let(:filepath) { 123 }
+
+ it 'returns false' do
+ expect(subject.valid?).to eq(false)
+ end
+ end
+
+ context 'when archive path is a symlink' do
+ let(:filepath) { File.join(Dir.tmpdir, 'symlink') }
+
+ before do
+ FileUtils.ln_s(filepath, filepath, force: true)
+ end
+
+ it 'returns false' do
+ expect(subject.valid?).to eq(false)
+ end
+ end
+
+ context 'when archive path is not a file' do
+ let(:filepath) { Dir.mktmpdir }
+ let(:filesize) { File.size(filepath) }
+
+ after do
+ FileUtils.rm_rf(filepath)
+ end
+
+ it 'returns false' do
+ expect(subject.valid?).to eq(false)
+ end
+ end
+ end
+
+ def create_compressed_file
+ Zlib::GzipWriter.open(filepath) do |gz|
+ gz.write('Hello World!')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index 4166eba4e8e..d8b8903c8ca 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -7,6 +7,8 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver, :with_license, feature_
let_it_be(:exportable_path) { 'project' }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+ let_it_be(:private_project) { create(:project, :private, group: group) }
+ let_it_be(:private_mr) { create(:merge_request, source_project: private_project, project: private_project) }
let_it_be(:project) { setup_project }
shared_examples 'saves project tree successfully' do
@@ -118,6 +120,13 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver, :with_license, feature_
expect(reviewer).not_to be_nil
expect(reviewer['user_id']).to eq(user.id)
end
+
+ it 'has merge requests system notes' do
+ system_notes = subject.first['notes'].select { |note| note['system'] }
+
+ expect(system_notes.size).to eq(1)
+ expect(system_notes.first['note']).to eq('merged')
+ end
end
context 'with snippets' do
@@ -492,6 +501,9 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver, :with_license, feature_
create(:milestone, project: project)
discussion_note = create(:discussion_note, noteable: issue, project: project)
mr_note = create(:note, noteable: merge_request, project: project)
+ create(:system_note, noteable: merge_request, project: project, author: user, note: 'merged')
+ private_system_note = "mentioned in merge request #{private_mr.to_reference(project)}"
+ create(:system_note, noteable: merge_request, project: project, author: user, note: private_system_note)
create(:note, noteable: snippet, project: project)
create(:note_on_commit,
author: user,