Class: Bundler::Audit::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler/audit/scanner.rb

Overview

Scans a Gemfile.lock for security issues.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root = Dir.pwd, gemfile_lock = 'Gemfile.lock', database = Database.new, config_dot_file = '.bundler-audit.yml') ⇒ Scanner

Initializes a scanner.

Parameters:

  • root (String) (defaults to: Dir.pwd)

    The path to the project root.

  • gemfile_lock (String) (defaults to: 'Gemfile.lock')

    Alternative name for the Gemfile.lock file.

  • database (Database) (defaults to: Database.new)

    The database to scan against.

  • config_dot_file (String) (defaults to: '.bundler-audit.yml')

    The file name of the bundler-audit config file.

Raises:

  • (Bundler::GemfileLockNotFound)

    The gemfile_lock file could not be found within the root directory.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/bundler/audit/scanner.rb', line 77

def initialize(root=Dir.pwd,gemfile_lock='Gemfile.lock',database=Database.new,config_dot_file='.bundler-audit.yml')
  @root     = File.expand_path(root)
  @database = database

  gemfile_lock_path = File.join(@root,gemfile_lock)

  unless File.file?(gemfile_lock_path)
    raise(Bundler::GemfileLockNotFound,"Could not find #{gemfile_lock.inspect} in #{@root.inspect}")
  end

  @lockfile = LockfileParser.new(File.read(gemfile_lock_path))

  config_dot_file_full_path = File.absolute_path(config_dot_file, @root)

  @config = if File.exist?(config_dot_file_full_path)
              Configuration.load(config_dot_file_full_path)
            else
              Configuration.new
            end
end

Instance Attribute Details

#configHash (readonly)

The configuration loaded from the .bundler-audit.yml file from the project.

Returns:

  • (Hash)


56
57
58
# File 'lib/bundler/audit/scanner.rb', line 56

def config
  @config
end

#databaseDatabase (readonly)

The advisory database.

Returns:



42
43
44
# File 'lib/bundler/audit/scanner.rb', line 42

def database
  @database
end

#lockfileBundler::LockfileParser (readonly)

The parsed Gemfile.lock from the project.

Returns:

  • (Bundler::LockfileParser)


50
51
52
# File 'lib/bundler/audit/scanner.rb', line 50

def lockfile
  @lockfile
end

#rootObject (readonly)

Project root directory



45
46
47
# File 'lib/bundler/audit/scanner.rb', line 45

def root
  @root
end

Instance Method Details

#report(options = {}) {|result| ... } ⇒ Report

Preforms a #scan and collects the results into a report.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :ignore (Array<String>)

    The advisories to ignore.

Yields:

  • (result)

    The given block will be passed the results of the scan.

Yield Parameters:

Returns:

Since:

  • 0.8.0



117
118
119
120
121
122
123
124
125
126
# File 'lib/bundler/audit/scanner.rb', line 117

def report(options={})
  report = Report.new()

  scan(options) do |result|
    report << result
    yield result if block_given?
  end

  return report
end

#scan(options = {}) {|result| ... } ⇒ Enumerator

Scans the project for issues.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :ignore (Array<String>)

    The advisories to ignore.

Yields:

  • (result)

    The given block will be passed the results of the scan.

Yield Parameters:

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.



146
147
148
149
150
151
152
153
# File 'lib/bundler/audit/scanner.rb', line 146

def scan(options={},&block)
  return enum_for(__method__,options) unless block

  scan_sources(options,&block)
  scan_specs(options,&block)

  return self
end

#scan_sources(options = {}) {|result| ... } ⇒ Enumerator

Scans the gem sources in the lockfile.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Yields:

  • (result)

    The given block will be passed the results of the scan.

Yield Parameters:

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Since:

  • 0.4.0



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/bundler/audit/scanner.rb', line 174

def scan_sources(options={})
  return enum_for(__method__,options) unless block_given?

  @lockfile.sources.map do |source|
    case source
    when Source::Git
      case source.uri
      when /^git:/, /^http:/
        unless internal_source?(source.uri)
          yield Results::InsecureSource.new(source.uri)
        end
      end
    when Source::Rubygems
      source.remotes.each do |uri|
        if (uri.scheme == 'http' && !internal_source?(uri))
          yield Results::InsecureSource.new(uri.to_s)
        end
      end
    end
  end
end

#scan_specs(options = {}) {|result| ... } ⇒ Enumerator

Scans the gem sources in the lockfile.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :ignore (Array<String>)

    The advisories to ignore.

Yields:

  • (result)

    The given block will be passed the results of the scan.

Yield Parameters:

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Since:

  • 0.4.0



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/bundler/audit/scanner.rb', line 218

def scan_specs(options={})
  return enum_for(__method__,options) unless block_given?

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

  @lockfile.specs.each do |gem|
    @database.check_gem(gem) do |advisory|
      is_ignored = ignore.intersect?(advisory.identifiers.to_set)
      next if is_ignored

      yield Results::UnpatchedGem.new(gem,advisory)
    end
  end
end