dependabot-npm_and_yarn 0.212.0 → 0.214.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/.eslintrc +1 -1
  3. data/helpers/README.md +2 -2
  4. data/helpers/lib/npm/vulnerability-auditor.js +7 -7
  5. data/helpers/package-lock.json +2781 -2547
  6. data/helpers/package.json +5 -5
  7. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package-lock.json +3 -3
  8. data/lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb +11 -2
  9. data/lib/dependabot/npm_and_yarn/file_fetcher.rb +90 -5
  10. data/lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb +15 -4
  11. data/lib/dependabot/npm_and_yarn/file_parser.rb +15 -6
  12. data/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +35 -21
  13. data/lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb +86 -7
  14. data/lib/dependabot/npm_and_yarn/file_updater/package_json_updater.rb +2 -2
  15. data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +96 -32
  16. data/lib/dependabot/npm_and_yarn/file_updater.rb +53 -1
  17. data/lib/dependabot/npm_and_yarn/helpers.rb +94 -0
  18. data/lib/dependabot/npm_and_yarn/package_name.rb +2 -2
  19. data/lib/dependabot/npm_and_yarn/requirement.rb +3 -3
  20. data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +43 -1
  21. data/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb +13 -14
  22. data/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb +16 -3
  23. data/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb +77 -23
  24. data/lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb +3 -4
  25. data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +19 -4
  26. data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +74 -30
  27. data/lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb +33 -8
  28. data/lib/dependabot/npm_and_yarn/update_checker.rb +76 -21
  29. data/lib/dependabot/npm_and_yarn/version.rb +1 -1
  30. data/lib/dependabot/npm_and_yarn.rb +2 -0
  31. metadata +13 -56
  32. data/lib/dependabot/npm_and_yarn/file_parser/yarn_lockfile_parser.rb +0 -59
@@ -4,6 +4,7 @@ require "dependabot/git_commit_checker"
4
4
  require "dependabot/update_checkers"
5
5
  require "dependabot/update_checkers/base"
6
6
  require "dependabot/shared_helpers"
7
+ require "set"
7
8
 
8
9
  module Dependabot
9
10
  module NpmAndYarn
@@ -16,6 +17,20 @@ module Dependabot
16
17
  require_relative "update_checker/conflicting_dependency_resolver"
17
18
  require_relative "update_checker/vulnerability_auditor"
18
19
 
20
+ def up_to_date?
21
+ return false if security_update? &&
22
+ dependency.version &&
23
+ version_class.correct?(dependency.version) &&
24
+ vulnerable_versions.any? &&
25
+ !vulnerable_versions.include?(current_version)
26
+
27
+ super
28
+ end
29
+
30
+ def vulnerable?
31
+ super || vulnerable_versions.any?
32
+ end
33
+
19
34
  def latest_version
20
35
  @latest_version ||=
21
36
  if git_dependency?
@@ -46,8 +61,8 @@ module Dependabot
46
61
  raise "Dependency not vulnerable!" unless vulnerable?
47
62
  # NOTE: we currently don't resolve transitive/sub-dependencies as
48
63
  # npm/yarn don't provide any control over updating to a specific
49
- # sub-dependency
50
- return latest_resolvable_version unless dependency.top_level?
64
+ # sub-dependency version
65
+ return latest_resolvable_transitive_security_fix_version_with_no_unlock unless dependency.top_level?
51
66
 
52
67
  # TODO: Might want to check resolvability here?
53
68
  lowest_security_fix_version
@@ -96,13 +111,19 @@ module Dependabot
96
111
  end
97
112
 
98
113
  def conflicting_dependencies
99
- ConflictingDependencyResolver.new(
114
+ conflicts = ConflictingDependencyResolver.new(
100
115
  dependency_files: dependency_files,
101
116
  credentials: credentials
102
117
  ).conflicting_dependencies(
103
118
  dependency: dependency,
104
119
  target_version: lowest_security_fix_version
105
120
  )
121
+
122
+ vulnerable = [vulnerability_audit].select do |hash|
123
+ !hash["fix_available"] && hash["explanation"]
124
+ end
125
+
126
+ conflicts + vulnerable
106
127
  end
107
128
 
108
129
  private
@@ -119,24 +140,30 @@ module Dependabot
119
140
  )
120
141
  end
121
142
 
143
+ def vulnerable_versions
144
+ @vulnerable_versions ||=
145
+ begin
146
+ all_versions = dependency.all_versions.
147
+ filter_map { |v| version_class.new(v) if version_class.correct?(v) }
148
+
149
+ all_versions.select do |v|
150
+ security_advisories.any? { |advisory| advisory.vulnerable?(v) }
151
+ end
152
+ end
153
+ end
154
+
122
155
  def latest_version_resolvable_with_full_unlock?
123
156
  return false unless latest_version
124
157
 
125
158
  return version_resolver.latest_version_resolvable_with_full_unlock? if dependency.top_level?
126
159
 
127
- return false unless transitive_security_updates_enabled? && security_advisories.any?
160
+ return false unless security_advisories.any?
128
161
 
129
162
  vulnerability_audit["fix_available"]
130
163
  end
131
164
 
132
- def transitive_security_updates_enabled?
133
- options.key?(:npm_transitive_security_updates)
134
- end
135
-
136
165
  def updated_dependencies_after_full_unlock
137
- if !dependency.top_level? && transitive_security_updates_enabled? && security_advisories.any?
138
- return conflicting_updated_dependencies
139
- end
166
+ return conflicting_updated_dependencies if !dependency.top_level? && security_advisories.any?
140
167
 
141
168
  version_resolver.dependency_updates_from_full_unlock.
142
169
  map { |update_details| build_updated_dependency(update_details) }
@@ -163,16 +190,18 @@ module Dependabot
163
190
  end
164
191
  # rubocop:enable Metrics/AbcSize
165
192
 
166
- # We don't need to update this but need to include it so it's described
167
- # in the PR and we'll pass validation that this dependency is at a
168
- # non-vulnerable version.
193
+ # We don't need to directly update the target dependency if it will
194
+ # be updated as a side effect of updating the parent. However, we need
195
+ # to include it so it's described in the PR and we'll pass validation
196
+ # that this dependency is at a non-vulnerable version.
169
197
  if updated_deps.none? { |dep| dep.name == dependency.name }
170
198
  target_version = vulnerability_audit["target_version"]
171
199
  updated_deps << build_updated_dependency(
172
200
  dependency: dependency,
173
201
  version: target_version,
174
202
  previous_version: dependency.version,
175
- removed: target_version.nil?
203
+ removed: target_version.nil?,
204
+ metadata: { information_only: true } # Instruct updater to not directly update this dependency
176
205
  )
177
206
  end
178
207
 
@@ -196,23 +225,35 @@ module Dependabot
196
225
  removed = update_details.fetch(:removed, false)
197
226
  version = update_details.fetch(:version).to_s unless removed
198
227
  previous_version = update_details.fetch(:previous_version)&.to_s
228
+ metadata = update_details.fetch(:metadata, {})
199
229
 
200
230
  Dependency.new(
201
231
  name: original_dep.name,
202
232
  version: version,
203
233
  requirements: RequirementsUpdater.new(
204
234
  requirements: original_dep.requirements,
205
- updated_source: original_dep == dependency ? updated_source : nil,
235
+ updated_source: original_dep == dependency ? updated_source : original_source(original_dep),
206
236
  latest_resolvable_version: version,
207
237
  update_strategy: requirements_update_strategy
208
238
  ).updated_requirements,
209
239
  previous_version: previous_version,
210
240
  previous_requirements: original_dep.requirements,
211
241
  package_manager: original_dep.package_manager,
212
- removed: removed
242
+ removed: removed,
243
+ metadata: metadata
213
244
  )
214
245
  end
215
246
 
247
+ def latest_resolvable_transitive_security_fix_version_with_no_unlock
248
+ fix_possible = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(
249
+ [latest_resolvable_version].compact,
250
+ security_advisories
251
+ ).any?
252
+ return nil unless fix_possible
253
+
254
+ latest_resolvable_version
255
+ end
256
+
216
257
  def latest_resolvable_version_with_no_unlock_for_git_dependency
217
258
  reqs = dependency.requirements.filter_map do |r|
218
259
  next if r.fetch(:requirement).nil?
@@ -298,7 +339,8 @@ module Dependabot
298
339
  credentials: credentials,
299
340
  dependency_files: dependency_files,
300
341
  latest_allowable_version: latest_version,
301
- latest_version_finder: latest_version_finder
342
+ latest_version_finder: latest_version_finder,
343
+ repo_contents_path: repo_contents_path
302
344
  )
303
345
  end
304
346
 
@@ -309,7 +351,8 @@ module Dependabot
309
351
  credentials: credentials,
310
352
  dependency_files: dependency_files,
311
353
  ignored_versions: ignored_versions,
312
- latest_allowable_version: latest_version
354
+ latest_allowable_version: latest_version,
355
+ repo_contents_path: repo_contents_path
313
356
  )
314
357
  end
315
358
 
@@ -365,12 +408,24 @@ module Dependabot
365
408
  return true if dependency_files.any? { |f| f.name == "lerna.json" }
366
409
 
367
410
  @library =
368
- LibraryDetector.new(package_json_file: package_json).library?
411
+ LibraryDetector.new(
412
+ package_json_file: package_json,
413
+ credentials: credentials,
414
+ dependency_files: dependency_files
415
+ ).library?
416
+ end
417
+
418
+ def security_update?
419
+ security_advisories.any?
369
420
  end
370
421
 
371
422
  def dependency_source_details
423
+ original_source(dependency)
424
+ end
425
+
426
+ def original_source(updated_dependency)
372
427
  sources =
373
- dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact.
428
+ updated_dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact.
374
429
  sort_by { |source| RegistryFinder.central_registry?(source[:url]) ? 1 : 0 }
375
430
 
376
431
  sources.first
@@ -15,7 +15,7 @@ module Dependabot
15
15
  attr_reader :build_info
16
16
 
17
17
  VERSION_PATTERN = Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?'
18
- ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/.freeze
18
+ ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
19
19
 
20
20
  def self.correct?(version)
21
21
  version = version.gsub(/^v/, "") if version.is_a?(String)
@@ -24,3 +24,5 @@ Dependabot::Dependency.register_production_check(
24
24
  groups.include?("dependencies")
25
25
  end
26
26
  )
27
+
28
+ Dependabot::Utils.register_always_clone("npm_and_yarn")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-npm_and_yarn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.212.0
4
+ version: 0.214.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-06 00:00:00.000000000 Z
11
+ date: 2022-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,42 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.212.0
19
+ version: 0.214.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.212.0
27
- - !ruby/object:Gem::Dependency
28
- name: debase
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '='
32
- - !ruby/object:Gem::Version
33
- version: 0.2.3
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '='
39
- - !ruby/object:Gem::Version
40
- version: 0.2.3
41
- - !ruby/object:Gem::Dependency
42
- name: debase-ruby_core_source
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '='
46
- - !ruby/object:Gem::Version
47
- version: 0.10.16
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '='
53
- - !ruby/object:Gem::Version
54
- version: 0.10.16
26
+ version: 0.214.0
55
27
  - !ruby/object:Gem::Dependency
56
28
  name: debug
57
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +58,14 @@ dependencies:
86
58
  requirements:
87
59
  - - "~>"
88
60
  - !ruby/object:Gem::Version
89
- version: 3.12.0
61
+ version: 4.0.0
90
62
  type: :development
91
63
  prerelease: false
92
64
  version_requirements: !ruby/object:Gem::Requirement
93
65
  requirements:
94
66
  - - "~>"
95
67
  - !ruby/object:Gem::Version
96
- version: 3.12.0
68
+ version: 4.0.0
97
69
  - !ruby/object:Gem::Dependency
98
70
  name: rake
99
71
  requirement: !ruby/object:Gem::Requirement
@@ -142,42 +114,28 @@ dependencies:
142
114
  requirements:
143
115
  - - "~>"
144
116
  - !ruby/object:Gem::Version
145
- version: 1.36.0
117
+ version: 1.39.0
146
118
  type: :development
147
119
  prerelease: false
148
120
  version_requirements: !ruby/object:Gem::Requirement
149
121
  requirements:
150
122
  - - "~>"
151
123
  - !ruby/object:Gem::Version
152
- version: 1.36.0
124
+ version: 1.39.0
153
125
  - !ruby/object:Gem::Dependency
154
126
  name: rubocop-performance
155
127
  requirement: !ruby/object:Gem::Requirement
156
128
  requirements:
157
129
  - - "~>"
158
130
  - !ruby/object:Gem::Version
159
- version: 1.14.2
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: 1.14.2
167
- - !ruby/object:Gem::Dependency
168
- name: ruby-debug-ide
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: 0.7.3
131
+ version: 1.15.0
174
132
  type: :development
175
133
  prerelease: false
176
134
  version_requirements: !ruby/object:Gem::Requirement
177
135
  requirements:
178
136
  - - "~>"
179
137
  - !ruby/object:Gem::Version
180
- version: 0.7.3
138
+ version: 1.15.0
181
139
  - !ruby/object:Gem::Dependency
182
140
  name: simplecov
183
141
  requirement: !ruby/object:Gem::Requirement
@@ -314,7 +272,6 @@ files:
314
272
  - lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb
315
273
  - lib/dependabot/npm_and_yarn/file_parser.rb
316
274
  - lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb
317
- - lib/dependabot/npm_and_yarn/file_parser/yarn_lockfile_parser.rb
318
275
  - lib/dependabot/npm_and_yarn/file_updater.rb
319
276
  - lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb
320
277
  - lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb
@@ -350,14 +307,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
350
307
  requirements:
351
308
  - - ">="
352
309
  - !ruby/object:Gem::Version
353
- version: 2.7.0
310
+ version: 3.1.0
354
311
  required_rubygems_version: !ruby/object:Gem::Requirement
355
312
  requirements:
356
313
  - - ">="
357
314
  - !ruby/object:Gem::Version
358
- version: 2.7.0
315
+ version: 3.1.0
359
316
  requirements: []
360
- rubygems_version: 3.1.6
317
+ rubygems_version: 3.3.7
361
318
  signing_key:
362
319
  specification_version: 4
363
320
  summary: JS support for dependabot
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/dependency_file"
4
- require "dependabot/npm_and_yarn/file_parser"
5
-
6
- module Dependabot
7
- module NpmAndYarn
8
- class FileParser
9
- class YarnLockfileParser
10
- def initialize(lockfile:)
11
- @content = lockfile.content
12
- end
13
-
14
- # This is *extremely* crude, but saves us from having to shell out
15
- # to Yarn, which may not be safe
16
- def parse
17
- yaml = convert_to_yaml
18
- lockfile_object = parse_as_yaml(yaml)
19
- expand_lockfile_requirements(lockfile_object)
20
- end
21
-
22
- private
23
-
24
- attr_reader :content
25
-
26
- # Transform lockfile to parseable YAML by wrapping requirements in
27
- # quotes, e.g. ("pkg@1.0.0":) and adding colon to nested
28
- # properties (version: "1.0.0")
29
- def convert_to_yaml
30
- sanitize_requirement = lambda do |line|
31
- return line unless line.match?(/^[\w"]/)
32
-
33
- "\"#{line.gsub(/\"|:\n$/, '')}\":\n"
34
- end
35
- add_missing_colon = ->(l) { l.sub(/(?<=\w|")\s(?=\w|")/, ": ") }
36
-
37
- content.lines.map(&sanitize_requirement).map(&add_missing_colon).join
38
- end
39
-
40
- def parse_as_yaml(yaml)
41
- YAML.safe_load(yaml)
42
- rescue Psych::SyntaxError, Psych::DisallowedClass, Psych::BadAlias
43
- {}
44
- end
45
-
46
- # Split all comma separated keys and duplicate the lockfile entry
47
- # so we get one entry per version requirement, this is needed when
48
- # one of the requirements specifies a file: requirement, e.g.
49
- # "pkga@file:./pkg, pkgb@1.0.0 and we want to check this in
50
- # `details_from_yarn_lock`
51
- def expand_lockfile_requirements(lockfile_object)
52
- lockfile_object.to_a.each_with_object({}) do |(names, val), res|
53
- names.split(", ").each { |name| res[name] = val }
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end