diff options
author | Kamil TrzciĆski <ayufan@ayufan.eu> | 2019-04-04 15:00:56 +0000 |
---|---|---|
committer | Sean McGivern <sean@gitlab.com> | 2019-04-04 15:00:56 +0000 |
commit | 8a833c720e91c7b4d764e85c30e3be18ee5221fd (patch) | |
tree | 54b714d8a8f18f6e6f0f8f5da56fae5203f002e8 /spec/lib | |
parent | 7926384ff32b9ad8833dcfffc9bb87d036c4bd21 (diff) | |
download | gitlab-ce-8a833c720e91c7b4d764e85c30e3be18ee5221fd.tar.gz |
Allow to use untrusted Regexp via feature flag
This brings support for untrusted regexp for 'only:refs:' when
enabled via feature flag: alllow_unsafe_ruby_regexp.
This is by default disabled, and should not be used in production
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/gitlab/ci/build/policy/refs_spec.rb | 26 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/policy_spec.rb | 67 | ||||
-rw-r--r-- | spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb | 68 |
3 files changed, 150 insertions, 11 deletions
diff --git a/spec/lib/gitlab/ci/build/policy/refs_spec.rb b/spec/lib/gitlab/ci/build/policy/refs_spec.rb index ec0450643c3..22ca681cfd3 100644 --- a/spec/lib/gitlab/ci/build/policy/refs_spec.rb +++ b/spec/lib/gitlab/ci/build/policy/refs_spec.rb @@ -101,6 +101,32 @@ describe Gitlab::Ci::Build::Policy::Refs do expect(described_class.new(['/fix-.*/'])) .not_to be_satisfied_by(pipeline) end + + context 'when unsafe regexp is used' do + let(:subject) { described_class.new(['/^(?!master).+/']) } + + context 'when allow_unsafe_ruby_regexp is disabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: false) + end + + it 'ignores invalid regexp' do + expect(subject) + .not_to be_satisfied_by(pipeline) + end + end + + context 'when allow_unsafe_ruby_regexp is enabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: true) + end + + it 'is satisfied by regexp' do + expect(subject) + .to be_satisfied_by(pipeline) + end + end + end end context 'malicious regexp' do diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb index 1c987e13a9a..fba5671594d 100644 --- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb @@ -1,4 +1,5 @@ require 'fast_spec_helper' +require 'support/helpers/stub_feature_flags' require_dependency 'active_model' describe Gitlab::Ci::Config::Entry::Policy do @@ -33,6 +34,44 @@ describe Gitlab::Ci::Config::Entry::Policy do end end + context 'when config is an empty regexp' do + let(:config) { ['//'] } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when using unsafe regexp' do + include StubFeatureFlags + + let(:config) { ['/^(?!master).+/'] } + + subject { described_class.new([regexp]) } + + context 'when allow_unsafe_ruby_regexp is disabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: false) + end + + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + context 'when allow_unsafe_ruby_regexp is enabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: true) + end + + it 'is valid' do + expect(entry).to be_valid + end + end + end + context 'when config is a special keyword' do let(:config) { %w[tags triggers branches] } @@ -67,6 +106,34 @@ describe Gitlab::Ci::Config::Entry::Policy do end end + context 'when using unsafe regexp' do + include StubFeatureFlags + + let(:config) { { refs: ['/^(?!master).+/'] } } + + subject { described_class.new([regexp]) } + + context 'when allow_unsafe_ruby_regexp is disabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: false) + end + + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + context 'when allow_unsafe_ruby_regexp is enabled' do + before do + stub_feature_flags(allow_unsafe_ruby_regexp: true) + end + + it 'is valid' do + expect(entry).to be_valid + end + end + end + context 'when specifying kubernetes policy' do let(:config) { { kubernetes: 'active' } } diff --git a/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb index 005d41580de..f1882e03581 100644 --- a/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb +++ b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb @@ -1,5 +1,6 @@ require 'fast_spec_helper' require 'support/shared_examples/malicious_regexp_shared_examples' +require 'support/helpers/stub_feature_flags' describe Gitlab::UntrustedRegexp::RubySyntax do describe '.matches_syntax?' do @@ -33,6 +34,12 @@ describe Gitlab::UntrustedRegexp::RubySyntax do end end + context 'when regexp is empty' do + it 'fabricates regexp correctly' do + expect(described_class.fabricate('//')).not_to be_nil + end + end + context 'when regexp is a raw pattern' do it 'returns error' do expect(described_class.fabricate('some .* thing')).to be_nil @@ -41,24 +48,63 @@ describe Gitlab::UntrustedRegexp::RubySyntax do end describe '.fabricate!' do - context 'when regexp is using /regexp/ scheme with flags' do - it 'fabricates regexp with a single flag' do - regexp = described_class.fabricate!('/something/i') + context 'safe regexp is used' do + context 'when regexp is using /regexp/ scheme with flags' do + it 'fabricates regexp with a single flag' do + regexp = described_class.fabricate!('/something/i') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?i)something') + expect(regexp.scan('SOMETHING')).to be_one + end - expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?i)something') - expect(regexp.scan('SOMETHING')).to be_one + it 'fabricates regexp with multiple flags' do + regexp = described_class.fabricate!('/something/im') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?im)something') + end + + it 'fabricates regexp without flags' do + regexp = described_class.fabricate!('/something/') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('something') + end end + end - it 'fabricates regexp with multiple flags' do - regexp = described_class.fabricate!('/something/im') + context 'when unsafe regexp is used' do + include StubFeatureFlags - expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?im)something') + before do + stub_feature_flags(allow_unsafe_ruby_regexp: true) + + allow(Gitlab::UntrustedRegexp).to receive(:new).and_raise(RegexpError) end - it 'fabricates regexp without flags' do - regexp = described_class.fabricate!('/something/') + context 'when no fallback is enabled' do + it 'raises an exception' do + expect { described_class.fabricate!('/something/') } + .to raise_error(RegexpError) + end + end + + context 'when fallback is used' do + it 'fabricates regexp with a single flag' do + regexp = described_class.fabricate!('/something/i', fallback: true) + + expect(regexp).to eq Regexp.new('something', Regexp::IGNORECASE) + end + + it 'fabricates regexp with multiple flags' do + regexp = described_class.fabricate!('/something/im', fallback: true) + + expect(regexp).to eq Regexp.new('something', Regexp::IGNORECASE | Regexp::MULTILINE) + end + + it 'fabricates regexp without flags' do + regexp = described_class.fabricate!('/something/', fallback: true) - expect(regexp).to eq Gitlab::UntrustedRegexp.new('something') + expect(regexp).to eq Regexp.new('something') + end end end |