class Bundler::Audit::Scanner
Constants
- INTERNAL_SUBNETS
List of internal IP address ranges.
@see tools.ietf.org/html/rfc1918#section-3 @see tools.ietf.org/html/rfc4193#section-8
- InsecureSource
Represents a plain-text source
- UnpatchedGem
Represents a gem that is covered by an
Advisory
Attributes
The advisory database
@return [Database]
The parsed `Gemfile.lock` from the project
@return [Bundler::LockfileParser]
Project root directory
Public Class Methods
Initializes a scanner.
@param [String] root
The path to the project root.
@param [String] gemfile_lock
Alternative name for the `Gemfile.lock` file.
# File lib/bundler/audit/scanner.rb, line 42 def initialize(root=Dir.pwd,gemfile_lock='Gemfile.lock') @root = File.expand_path(root) @database = Database.new @lockfile = LockfileParser.new( File.read(File.join(@root,gemfile_lock)) ) end
Public Instance Methods
Scans the project for issues.
@param [Hash] options
Additional options.
@option options [Array<String>] :ignore
The advisories to ignore.
@yield [result]
The given block will be passed the results of the scan.
@yieldparam [InsecureSource, UnpatchedGem] result
A result from the scan.
@return [Enumerator]
If no block is given, an Enumerator will be returned.
# File lib/bundler/audit/scanner.rb, line 68 def scan(options={},&block) return enum_for(__method__,options) unless block ignore = Set[] ignore += options[:ignore] if options[:ignore] scan_sources(options,&block) scan_specs(options,&block) return self end
Scans the gem sources in the lockfile.
@param [Hash] options
Additional options.
@yield [result]
The given block will be passed the results of the scan.
@yieldparam [InsecureSource] result
A result from the scan.
@return [Enumerator]
If no block is given, an Enumerator will be returned.
@api semipublic
@since 0.4.0
# File lib/bundler/audit/scanner.rb, line 99 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 InsecureSource.new(source.uri) end end when Source::Rubygems source.remotes.each do |uri| if (uri.scheme == 'http' && !internal_source?(uri)) yield InsecureSource.new(uri.to_s) end end end end end
Scans the gem sources in the lockfile.
@param [Hash] options
Additional options.
@option options [Array<String>] :ignore
The advisories to ignore.
@yield [result]
The given block will be passed the results of the scan.
@yieldparam [UnpatchedGem] result
A result from the scan.
@return [Enumerator]
If no block is given, an Enumerator will be returned.
@api semipublic
@since 0.4.0
# File lib/bundler/audit/scanner.rb, line 143 def scan_specs(options={}) return enum_for(__method__,options) unless block_given? ignore = Set[] ignore += options[:ignore] if options[:ignore] @lockfile.specs.each do |gem| @database.check_gem(gem) do |advisory| unless (ignore.include?(advisory.cve_id) || ignore.include?(advisory.osvdb_id)) yield UnpatchedGem.new(gem,advisory) end end end end
Private Instance Methods
Determines whether a host is internal.
@param [String] host
The hostname.
@return [Boolean]
# File lib/bundler/audit/scanner.rb, line 183 def internal_host?(host) Resolv.getaddresses(host).all? { |ip| internal_ip?(ip) } rescue URI::Error false end
Determines whether an IP is internal.
@param [String] ip
The IPv4/IPv6 address.
@return [Boolean]
# File lib/bundler/audit/scanner.rb, line 208 def internal_ip?(ip) INTERNAL_SUBNETS.any? { |subnet| subnet.include?(ip) } end
Determines whether a source is internal.
@param [URI, String] uri
The URI.
@return [Boolean]
# File lib/bundler/audit/scanner.rb, line 169 def internal_source?(uri) uri = URI(uri) internal_host?(uri.host) if uri.host end