dependabot-common 0.99.7 → 0.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dependabot/security_advisory.rb +83 -0
- data/lib/dependabot/update_checkers/base.rb +40 -7
- data/lib/dependabot/version.rb +1 -1
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f9668f1967a71d3410cbc64d841b11b6489c2fcb18c44fe93c46c41a04fba5d7
         | 
| 4 | 
            +
              data.tar.gz: 61c5d476ca5df6fa4c0d071f325708db732de08a5104cf88d4fdf9a510f00e34
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 66bccb0d40bff7af3d3bdb7e64b8818f52f33fffac90c8d789bed1257be1550269bf85516e95b2fad63548cf2c2ff60d11e0119b34bcd4e67de6531bd51ca87f
         | 
| 7 | 
            +
              data.tar.gz: 77d31ecd4dbf6e0c46e6c9b927197d4c8494ce134bfbcb900a5f81ea3a535b6b2feced921aedbace21502bfc7460a3d1dcea36e0d60d31104a8896f1de993b7e
         | 
| @@ -0,0 +1,83 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "rubygems_version_patch"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Dependabot
         | 
| 6 | 
            +
              class SecurityAdvisory
         | 
| 7 | 
            +
                attr_reader :vulnerable_versions, :safe_versions, :package_manager
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize(vulnerable_versions: [], safe_versions: [], package_manager:)
         | 
| 10 | 
            +
                  @vulnerable_versions = vulnerable_versions || []
         | 
| 11 | 
            +
                  @safe_versions = safe_versions || []
         | 
| 12 | 
            +
                  @package_manager = package_manager
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  convert_string_version_requirements
         | 
| 15 | 
            +
                  check_version_requirements
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def vulnerable?(version)
         | 
| 19 | 
            +
                  unless version.is_a?(version_class)
         | 
| 20 | 
            +
                    raise ArgumentError, "must be a #{version_class}"
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  in_safe_range =
         | 
| 24 | 
            +
                    safe_versions.
         | 
| 25 | 
            +
                    any? { |r| r.satisfied_by?(version_class.new(version)) }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  # If version is known safe for this advisory, it's not vulnerable
         | 
| 28 | 
            +
                  return false if in_safe_range
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  in_vulnerable_range =
         | 
| 31 | 
            +
                    vulnerable_versions.
         | 
| 32 | 
            +
                    any? { |r| r.satisfied_by?(version_class.new(version)) }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  # If in the vulnerable range and not known safe, it's vulnerable
         | 
| 35 | 
            +
                  return true if in_vulnerable_range
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  # If a vulnerable range present but not met, it's not vulnerable
         | 
| 38 | 
            +
                  return false if vulnerable_versions.any?
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  # Finally, if no vulnerable range provided, but a safe range provided,
         | 
| 41 | 
            +
                  # and this versions isn't included (checked earler), it's vulnerable
         | 
| 42 | 
            +
                  safe_versions.any?
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                private
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def convert_string_version_requirements
         | 
| 48 | 
            +
                  @vulnerable_versions = vulnerable_versions.flat_map do |vuln_str|
         | 
| 49 | 
            +
                    next vuln_str unless vuln_str.is_a?(String)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    requirement_class.requirements_array(vuln_str)
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  @safe_versions = safe_versions.flat_map do |safe_str|
         | 
| 55 | 
            +
                    next safe_str unless safe_str.is_a?(String)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    requirement_class.requirements_array(safe_str)
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def check_version_requirements
         | 
| 62 | 
            +
                  unless vulnerable_versions.is_a?(Array) &&
         | 
| 63 | 
            +
                         vulnerable_versions.all? { |i| requirement_class <= i.class }
         | 
| 64 | 
            +
                    raise ArgumentError, "vulnerable_versions must be an array "\
         | 
| 65 | 
            +
                                         "of #{requirement_class} instances"
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  unless safe_versions.is_a?(Array) &&
         | 
| 69 | 
            +
                         safe_versions.all? { |i| requirement_class <= i.class }
         | 
| 70 | 
            +
                    raise ArgumentError, "safe_versions must be an array "\
         | 
| 71 | 
            +
                                         "of #{requirement_class} instances"
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def version_class
         | 
| 76 | 
            +
                  Utils.version_class_for_package_manager(package_manager)
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def requirement_class
         | 
| 80 | 
            +
                  Utils.requirement_class_for_package_manager(package_manager)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
            end
         | 
| @@ -2,24 +2,28 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require "json"
         | 
| 4 4 | 
             
            require "dependabot/utils"
         | 
| 5 | 
            +
            require "dependabot/security_advisory"
         | 
| 5 6 |  | 
| 6 7 | 
             
            module Dependabot
         | 
| 7 8 | 
             
              module UpdateCheckers
         | 
| 8 9 | 
             
                class Base
         | 
| 9 10 | 
             
                  attr_reader :dependency, :dependency_files, :credentials,
         | 
| 10 | 
            -
                              :ignored_versions, : | 
| 11 | 
            +
                              :ignored_versions, :security_advisories,
         | 
| 12 | 
            +
                              :requirements_update_strategy
         | 
| 11 13 |  | 
| 12 14 | 
             
                  def initialize(dependency:, dependency_files:, credentials:,
         | 
| 13 | 
            -
                                 ignored_versions: [],  | 
| 15 | 
            +
                                 ignored_versions: [], security_advisories: [],
         | 
| 16 | 
            +
                                 requirements_update_strategy: nil)
         | 
| 14 17 | 
             
                    @dependency = dependency
         | 
| 15 18 | 
             
                    @dependency_files = dependency_files
         | 
| 16 19 | 
             
                    @credentials = credentials
         | 
| 17 20 | 
             
                    @requirements_update_strategy = requirements_update_strategy
         | 
| 18 21 | 
             
                    @ignored_versions = ignored_versions
         | 
| 22 | 
            +
                    @security_advisories = security_advisories
         | 
| 19 23 | 
             
                  end
         | 
| 20 24 |  | 
| 21 25 | 
             
                  def up_to_date?
         | 
| 22 | 
            -
                    if dependency. | 
| 26 | 
            +
                    if dependency.version
         | 
| 23 27 | 
             
                      version_up_to_date?
         | 
| 24 28 | 
             
                    else
         | 
| 25 29 | 
             
                      requirements_up_to_date?
         | 
| @@ -30,7 +34,7 @@ module Dependabot | |
| 30 34 | 
             
                    # Can't update if all versions are being ignored
         | 
| 31 35 | 
             
                    return false if ignore_reqs.include?(requirement_class.new(">= 0"))
         | 
| 32 36 |  | 
| 33 | 
            -
                    if dependency. | 
| 37 | 
            +
                    if dependency.version
         | 
| 34 38 | 
             
                      version_can_update?(requirements_to_unlock: requirements_to_unlock)
         | 
| 35 39 | 
             
                    else
         | 
| 36 40 | 
             
                      # TODO: Handle full unlock updates for dependencies without a lockfile
         | 
| @@ -57,10 +61,25 @@ module Dependabot | |
| 57 61 | 
             
                    raise NotImplementedError
         | 
| 58 62 | 
             
                  end
         | 
| 59 63 |  | 
| 64 | 
            +
                  def preferred_resolvable_version
         | 
| 65 | 
            +
                    # If this dependency is vulnerable, prefer trying to update to the
         | 
| 66 | 
            +
                    # lowest_resolvable_security_fix_version. Otherwise update all the way
         | 
| 67 | 
            +
                    # to the latest_resolvable_version.
         | 
| 68 | 
            +
                    return lowest_resolvable_security_fix_version if vulnerable?
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    latest_resolvable_version
         | 
| 71 | 
            +
                  rescue NotImplementedError
         | 
| 72 | 
            +
                    latest_resolvable_version
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 60 75 | 
             
                  def latest_resolvable_version
         | 
| 61 76 | 
             
                    raise NotImplementedError
         | 
| 62 77 | 
             
                  end
         | 
| 63 78 |  | 
| 79 | 
            +
                  def lowest_resolvable_security_fix_version
         | 
| 80 | 
            +
                    raise NotImplementedError
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 64 83 | 
             
                  def latest_resolvable_version_with_no_unlock
         | 
| 65 84 | 
             
                    raise NotImplementedError
         | 
| 66 85 | 
             
                  end
         | 
| @@ -84,6 +103,20 @@ module Dependabot | |
| 84 103 | 
             
                    true
         | 
| 85 104 | 
             
                  end
         | 
| 86 105 |  | 
| 106 | 
            +
                  def vulnerable?
         | 
| 107 | 
            +
                    return false if security_advisories.none?
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    # Can't (currently) detect whether dependencies without a version
         | 
| 110 | 
            +
                    # (i.e., for repos without a lockfile) are vulnerable
         | 
| 111 | 
            +
                    return false unless dependency.version
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    # Can't (currently) detect whether git dependencies are vulnerable
         | 
| 114 | 
            +
                    return false if existing_version_is_sha?
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    version = version_class.new(dependency.version)
         | 
| 117 | 
            +
                    security_advisories.any? { |a| a.vulnerable?(version) }
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
             | 
| 87 120 | 
             
                  private
         | 
| 88 121 |  | 
| 89 122 | 
             
                  def latest_version_resolvable_with_full_unlock?
         | 
| @@ -104,7 +137,7 @@ module Dependabot | |
| 104 137 | 
             
                  def updated_dependency_with_own_req_unlock
         | 
| 105 138 | 
             
                    Dependency.new(
         | 
| 106 139 | 
             
                      name: dependency.name,
         | 
| 107 | 
            -
                      version:  | 
| 140 | 
            +
                      version: preferred_resolvable_version.to_s,
         | 
| 108 141 | 
             
                      requirements: updated_requirements,
         | 
| 109 142 | 
             
                      previous_version: dependency.version,
         | 
| 110 143 | 
             
                      previous_requirements: dependency.requirements,
         | 
| @@ -153,7 +186,7 @@ module Dependabot | |
| 153 186 | 
             
                      new_version = latest_resolvable_version_with_no_unlock
         | 
| 154 187 | 
             
                      new_version && !new_version.to_s.start_with?(dependency.version)
         | 
| 155 188 | 
             
                    when :own
         | 
| 156 | 
            -
                      new_version =  | 
| 189 | 
            +
                      new_version = preferred_resolvable_version
         | 
| 157 190 | 
             
                      new_version && !new_version.to_s.start_with?(dependency.version)
         | 
| 158 191 | 
             
                    when :all
         | 
| 159 192 | 
             
                      latest_version_resolvable_with_full_unlock?
         | 
| @@ -180,7 +213,7 @@ module Dependabot | |
| 180 213 | 
             
                      new_version = latest_resolvable_version_with_no_unlock
         | 
| 181 214 | 
             
                      new_version && new_version > version_class.new(dependency.version)
         | 
| 182 215 | 
             
                    when :own
         | 
| 183 | 
            -
                      new_version =  | 
| 216 | 
            +
                      new_version = preferred_resolvable_version
         | 
| 184 217 | 
             
                      new_version && new_version > version_class.new(dependency.version)
         | 
| 185 218 | 
             
                    when :all
         | 
| 186 219 | 
             
                      latest_version_resolvable_with_full_unlock?
         | 
    
        data/lib/dependabot/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: dependabot-common
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.100.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dependabot
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019-04- | 
| 11 | 
            +
            date: 2019-04-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: aws-sdk-ecr
         | 
| @@ -345,6 +345,7 @@ files: | |
| 345 345 | 
             
            - lib/dependabot/pull_request_creator/message_builder.rb
         | 
| 346 346 | 
             
            - lib/dependabot/pull_request_updater.rb
         | 
| 347 347 | 
             
            - lib/dependabot/pull_request_updater/github.rb
         | 
| 348 | 
            +
            - lib/dependabot/security_advisory.rb
         | 
| 348 349 | 
             
            - lib/dependabot/shared_helpers.rb
         | 
| 349 350 | 
             
            - lib/dependabot/source.rb
         | 
| 350 351 | 
             
            - lib/dependabot/update_checkers.rb
         |