Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/bundler/audit/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class CLI < ::Thor
method_option :quiet, type: :boolean, aliases: '-q'
method_option :verbose, type: :boolean, aliases: '-v'
method_option :ignore, type: :array, aliases: '-i'
method_option :exclude, type: :array, aliases: '-e'
method_option :update, type: :boolean, aliases: '-u'
method_option :database, type: :string, aliases: '-D',
default: Database::DEFAULT_PATH
Expand Down Expand Up @@ -73,7 +74,7 @@ def check(dir=Dir.pwd)
exit 1
end

report = scanner.report(ignore: options.ignore)
report = scanner.report(ignore: options.ignore, exclude: options.exclude)

output = if options[:output]
File.new(options[:output],'w')
Expand Down
23 changes: 22 additions & 1 deletion lib/bundler/audit/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ def self.load(file_path)
end

config[:ignore] = value.children.map(&:value)
when 'exclude'
unless value.is_a?(YAML::Nodes::Sequence)
raise(InvalidConfigurationError,"'exclude' key found in config file, but is not an Array")
end

unless value.children.all? { |node| node.is_a?(YAML::Nodes::Scalar) }
raise(InvalidConfigurationError,"'exclude' array in config file contains a non-String")
end

config[:exclude] = value.children.map(&:value)
end
end

Expand All @@ -90,6 +100,13 @@ def self.load(file_path)
#
attr_reader :ignore

#
# The list of gem names to exclude from scanning.
#
# @return [Set<String>]
#
attr_reader :exclude

#
# Initializes the configuration.
#
Expand All @@ -99,8 +116,12 @@ def self.load(file_path)
# @option config [Array<String>] :ignore
# The list of advisory IDs to ignore.
#
# @option config [Array<String>] :exclude
# The list of gem names to exclude from scanning.
#
def initialize(config={})
@ignore = Set.new(config[:ignore])
@ignore = Set.new(config[:ignore])
@exclude = Set.new(config[:exclude])
end

end
Expand Down
17 changes: 17 additions & 0 deletions lib/bundler/audit/scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ def initialize(root=Dir.pwd,gemfile_lock='Gemfile.lock',database=Database.new,co
# @option options [Array<String>] :ignore
# The advisories to ignore.
#
# @option options [Array<String>] :exclude
# The gem names to exclude from scanning.
#
# @yield [result]
# The given block will be passed the results of the scan.
#
Expand Down Expand Up @@ -134,6 +137,9 @@ def report(options={})
# @option options [Array<String>] :ignore
# The advisories to ignore.
#
# @option options [Array<String>] :exclude
# The gem names to exclude from scanning.
#
# @yield [result]
# The given block will be passed the results of the scan.
#
Expand Down Expand Up @@ -202,6 +208,9 @@ def scan_sources(options={})
# @option options [Array<String>] :ignore
# The advisories to ignore.
#
# @option options [Array<String>] :exclude
# The gem names to exclude from scanning.
#
# @yield [result]
# The given block will be passed the results of the scan.
#
Expand All @@ -224,7 +233,15 @@ def scan_specs(options={})
config.ignore
end

exclude = if options[:exclude]
Set.new(options[:exclude])
else
config.exclude
end

@lockfile.specs.each do |gem|
next if exclude.include?(gem.name)

@database.check_gem(gem) do |advisory|
is_ignored = ignore.intersect?(advisory.identifiers.to_set)
next if is_ignored
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
exclude:
- activerecord
3 changes: 3 additions & 0 deletions spec/bundle/unpatched_gems_with_exclude_configuration/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source 'https://rubygems.org'

gem 'activerecord', '3.2.10'
40 changes: 40 additions & 0 deletions spec/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@
end
end
end

context "when exclude is not an array" do
let(:path) { File.join(fixtures_dir,'bad','exclude_is_not_an_array.yml') }

it 'raises a validation error' do
expect { subject }.to raise_error(described_class::InvalidConfigurationError)
end
end

context 'when exclude is an array' do
context 'when exclude only contains strings' do
let(:path) { File.join(fixtures_dir,'valid_with_exclude.yml') }

it { should be_a(described_class) }
end

describe "when exclude contains non-strings" do
let(:path) { File.join(fixtures_dir,'bad','exclude_contains_a_non_string.yml') }

it "raises a validation error" do
expect { subject }.to raise_error(described_class::InvalidConfigurationError)
end
end
end
end
end

Expand All @@ -62,6 +86,11 @@
expect(subject.ignore).to be_kind_of(Set)
expect(subject.ignore).to be_empty
end

it "must set @exclude to an empty Set" do
expect(subject.exclude).to be_kind_of(Set)
expect(subject.exclude).to be_empty
end
end

context "when given :ignore" do
Expand All @@ -74,5 +103,16 @@
expect(subject.ignore).to be == Set.new(advisory_ids)
end
end

context "when given :exclude" do
let(:gem_names) { %w[activestorage actiontext] }

subject { described_class.new(exclude: gem_names) }

it "must initialize @exclude to contain :exclude" do
expect(subject.exclude).to be_kind_of(Set)
expect(subject.exclude).to be == Set.new(gem_names)
end
end
end
end
4 changes: 4 additions & 0 deletions spec/fixtures/config/bad/exclude_contains_a_non_string.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
exclude:
- activestorage
- hello: world
3 changes: 3 additions & 0 deletions spec/fixtures/config/bad/exclude_is_not_an_array.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
exclude:
foo: bar
7 changes: 7 additions & 0 deletions spec/fixtures/config/valid_with_exclude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
ignore:
- CVE-123
- CVE-456
exclude:
- activestorage
- actiontext
24 changes: 24 additions & 0 deletions spec/scanner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@
expect(ids).not_to include('CVE-2013-0156')
end
end

context "when the :exclude option is given" do
subject { super().scan(exclude: ['activerecord']) }

it "should not include results for the excluded gem" do
gem_names = subject.map { |result| result.gem.name }

expect(gem_names).not_to include('activerecord')
end
end
end

context "when auditing a bundle with insecure sources" do
Expand All @@ -67,6 +77,20 @@
end
end

context "when the exclude option is configured in .bundler-audit.yml" do
let(:bundle) { 'unpatched_gems_with_exclude_configuration' }
let(:directory) { File.join('spec','bundle',bundle) }
let(:scanner) { described_class.new(directory) }

subject { scanner.scan }

it "should not include results for the excluded gem" do
gem_names = subject.map { |result| result.gem.name }

expect(gem_names).not_to include('activerecord')
end
end

context "when the ignore option is configured in .bundler-audit.yml" do
let(:bundle) { 'unpatched_gems_with_dot_configuration' }
let(:directory) { File.join('spec','bundle',bundle) }
Expand Down