From ba60d4f6e4f3a6d3cb56c9320f475bee8f0b38da Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 22 Jun 2017 15:33:17 +0000 Subject: Merge branch '24570-use-re2-for-user-supplied-regexp-9-3' into 'security-9-3' 24570 use re2 for user supplied regexp 9 3 See merge request !2129 --- spec/lib/gitlab/ci/trace/stream_spec.rb | 7 +++ spec/lib/gitlab/route_map_spec.rb | 13 ++++++ spec/lib/gitlab/untrusted_regexp_spec.rb | 80 ++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 spec/lib/gitlab/untrusted_regexp_spec.rb (limited to 'spec/lib') diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb index bbb3f9912a3..13f0338b6aa 100644 --- a/spec/lib/gitlab/ci/trace/stream_spec.rb +++ b/spec/lib/gitlab/ci/trace/stream_spec.rb @@ -293,5 +293,12 @@ describe Gitlab::Ci::Trace::Stream do it { is_expected.to eq("65") } end + + context 'malicious regexp' do + let(:data) { malicious_text } + let(:regex) { malicious_regexp } + + include_examples 'malicious regexp' + end end end diff --git a/spec/lib/gitlab/route_map_spec.rb b/spec/lib/gitlab/route_map_spec.rb index 21c00c6e5b8..e8feb21e4d7 100644 --- a/spec/lib/gitlab/route_map_spec.rb +++ b/spec/lib/gitlab/route_map_spec.rb @@ -55,6 +55,19 @@ describe Gitlab::RouteMap, lib: true do end describe '#public_path_for_source_path' do + context 'malicious regexp' do + include_examples 'malicious regexp' + + subject do + map = described_class.new(<<-"MAP".strip_heredoc) + - source: '#{malicious_regexp}' + public: '/' + MAP + + map.public_path_for_source_path(malicious_text) + end + end + subject do described_class.new(<<-'MAP'.strip_heredoc) # Team data diff --git a/spec/lib/gitlab/untrusted_regexp_spec.rb b/spec/lib/gitlab/untrusted_regexp_spec.rb new file mode 100644 index 00000000000..66045917cb3 --- /dev/null +++ b/spec/lib/gitlab/untrusted_regexp_spec.rb @@ -0,0 +1,80 @@ +require 'spec_helper' + +describe Gitlab::UntrustedRegexp do + describe '#initialize' do + subject { described_class.new(pattern) } + + context 'invalid regexp' do + let(:pattern) { '[' } + + it { expect { subject }.to raise_error(RegexpError) } + end + end + + describe '#replace_all' do + it 'replaces all instances of the match in a string' do + result = described_class.new('foo').replace_all('foo bar foo', 'oof') + + expect(result).to eq('oof bar oof') + end + end + + describe '#replace' do + it 'replaces the first instance of the match in a string' do + result = described_class.new('foo').replace('foo bar foo', 'oof') + + expect(result).to eq('oof bar foo') + end + end + + describe '#===' do + it 'returns true for a match' do + result = described_class.new('foo') === 'a foo here' + + expect(result).to be_truthy + end + + it 'returns false for no match' do + result = described_class.new('foo') === 'a bar here' + + expect(result).to be_falsy + end + end + + describe '#scan' do + subject { described_class.new(regexp).scan(text) } + context 'malicious regexp' do + let(:text) { malicious_text } + let(:regexp) { malicious_regexp } + + include_examples 'malicious regexp' + end + + context 'no capture group' do + let(:regexp) { '.+' } + let(:text) { 'foo' } + + it 'returns the whole match' do + is_expected.to eq(['foo']) + end + end + + context 'one capture group' do + let(:regexp) { '(f).+' } + let(:text) { 'foo' } + + it 'returns the captured part' do + is_expected.to eq([%w[f]]) + end + end + + context 'two capture groups' do + let(:regexp) { '(f).(o)' } + let(:text) { 'foo' } + + it 'returns the captured parts' do + is_expected.to eq([%w[f o]]) + end + end + end +end -- cgit v1.2.3