dependabot-npm_and_yarn 0.326.0 → 0.327.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4842f09d3dc4cb14c7092b9281109ab583e8bad0d47db88961a09c6a7e58fc3
4
- data.tar.gz: 6497cd3f3b7e8ad082dd51341a2c52eeacbab331e1d7364382ae77b55cd9b7df
3
+ metadata.gz: 9caa8e27e4f8a3e9572f91367b5b781657cd85c3c4e71a723ac95098f799b64a
4
+ data.tar.gz: 60e07515a118c5ff572be0b10a20a4e7884c23d53ca4461e9fa9675232b15dfd
5
5
  SHA512:
6
- metadata.gz: 8fee137d5966dfff6fb1e689f98a060ecc86fe186f2c2f11d6a9df527aae7efe41e0d3d63faa23fe246708887c975cabc8257986bf2c8dad681b498ee6bb5bd7
7
- data.tar.gz: 1cbb7f8c7653de3509516f5aa9abdd13be8c9e277f97242346e1c0b97a0d9e32770e97f2eb356e23c0d496e2d2c71508c2242811ab025f9eede4cbcc8f9d9df4
6
+ metadata.gz: aeb056544931600953d773a5b3564a4d8ba42aeb970363894499fe0a768dddbede3cd4ee872a25bdedf10c765b44230648dfa349909bb5cac88158e6c22edb49
7
+ data.tar.gz: f38ca1a0d104851e80320a8a9927138d66a31c9fa096c3bb37711fe4aa99cfae9e944233e5cdd7ba32f58cab4e5ca99bc7b53e9d39b55c25a8fbce4b3636eebc
@@ -73,7 +73,8 @@ async function findVulnerableDependencies(directory, advisories) {
73
73
  return response
74
74
  }
75
75
  const vuln = auditReport.get(name)
76
- const version = [...vuln.nodes][0].version
76
+ const vulnNodesHighestLevelFirst = [...vuln.nodes].sort((a, b) => a.depth - b.depth);
77
+ const version = vulnNodesHighestLevelFirst[0].version
77
78
  const fixAvailable = vuln.fixAvailable
78
79
 
79
80
  response.current_version = version
@@ -113,6 +114,7 @@ async function findVulnerableDependencies(directory, advisories) {
113
114
 
114
115
  response.fix_updates.push({
115
116
  dependency_name: fixUpdateNode.name,
117
+ dependency_location: fixUpdateNode.location,
116
118
  current_version: fixUpdateNode.version,
117
119
  top_level_ancestors: fixUpdateNodeTopLevelAncestors,
118
120
  })
@@ -128,7 +130,8 @@ async function findVulnerableDependencies(directory, advisories) {
128
130
 
129
131
  for (const update of response.fix_updates) {
130
132
  update.target_version =
131
- fixTree.children.get(update.dependency_name)?.version
133
+ lookupChildLocation(fixTree, update.dependency_location)?.version
134
+ delete update.dependency_location // Not needed in the output.
132
135
  }
133
136
 
134
137
  return response
@@ -217,6 +220,30 @@ function groupBy(elems, fn) {
217
220
  return groups
218
221
  }
219
222
 
223
+ /**
224
+ * Look up the child node at the given location in the tree rooted at `root`.
225
+ * `root` is an ArboristNode, and `location` is a string containing the normalized
226
+ * path to the child node, relative to the root. This string can be taken from
227
+ * ArboristNode.location and will be of the form "node_modules/foo/node_modules/bar".
228
+ */
229
+ function lookupChildLocation(root, location) {
230
+ if (!location.startsWith('node_modules/')) {
231
+ // The location must start with 'node_modules/' to be valid.
232
+ return null;
233
+ }
234
+ const parts = location
235
+ .substring('node_modules/'.length)
236
+ .split('/node_modules/')
237
+ let current = root
238
+ for (const part of parts) {
239
+ current = current.children.get(part)
240
+ if (!current) {
241
+ return null
242
+ }
243
+ }
244
+ return current
245
+ }
246
+
220
247
  async function loadNpmConfig() {
221
248
  const configOutput = await exec('npm config ls --json')
222
249
  return JSON.parse(configOutput.stdout)
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "test-vulnerability-auditor-simple",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "test-vulnerability-auditor-simple",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "@dependabot-fixtures/npm-parent-dependency": "^2.0.0"
12
+ }
13
+ },
14
+ "node_modules/@dependabot-fixtures/npm-intermediate-dependency": {
15
+ "version": "0.0.1",
16
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-intermediate-dependency/-/npm-intermediate-dependency-0.0.1.tgz",
17
+ "integrity": "sha512-/N77Dzpfg8BIfFgpJrMk86ueUYTVhmpc4RobuHpIpKSc3GZr4Ltu4au92brnUGk66UkzgrMmtgqRXO8OrOspKQ==",
18
+ "license": "ISC",
19
+ "dependencies": {
20
+ "@dependabot-fixtures/npm-transitive-dependency": "1.0.0"
21
+ }
22
+ },
23
+ "node_modules/@dependabot-fixtures/npm-parent-dependency": {
24
+ "version": "2.0.0",
25
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-parent-dependency/-/npm-parent-dependency-2.0.0.tgz",
26
+ "integrity": "sha512-5LtLEL1yzO2TdkNX3R9cvr+nKmhw5h4xM0wkFTJeK14wxlI9d8gEYA+I2hUi+IP96ucBSztAnOgZVwoJHEZb6A==",
27
+ "license": "ISC",
28
+ "dependencies": {
29
+ "@dependabot-fixtures/npm-intermediate-dependency": "0.0.1"
30
+ }
31
+ },
32
+ "node_modules/@dependabot-fixtures/npm-transitive-dependency": {
33
+ "version": "1.0.0",
34
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-transitive-dependency/-/npm-transitive-dependency-1.0.0.tgz",
35
+ "integrity": "sha512-nFbzQH0TRgdzSA2/FH6MPnxZDpD+5Bgz00aD5Edgbc1wY/k8VC9s7lnk22dBTgJLwoY7MgbrnAf9rAvN08hHVg==",
36
+ "license": "ISC"
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "test-vulnerability-auditor-simple",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "dependencies": {
10
+ "@dependabot-fixtures/npm-parent-dependency": "^2.0.0"
11
+ }
12
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "test-vulnerability-update-needed-across-two-versions",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "test-vulnerability-update-needed-across-two-versions",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "@msgpack/msgpack": "^2.7.2",
12
+ "wireql-client": "^1.0.3"
13
+ }
14
+ },
15
+ "node_modules/@msgpack/msgpack": {
16
+ "version": "2.7.2",
17
+ "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.7.2.tgz",
18
+ "integrity": "sha512-rYEi46+gIzufyYUAoHDnRzkWGxajpD9vVXFQ3g1vbjrBm6P7MBmm+s/fqPa46sxa+8FOUdEuRQKaugo5a4JWpw==",
19
+ "license": "ISC",
20
+ "engines": {
21
+ "node": ">= 10"
22
+ }
23
+ },
24
+ "node_modules/eventemitter3": {
25
+ "version": "5.0.1",
26
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
27
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
28
+ "license": "MIT"
29
+ },
30
+ "node_modules/typescript": {
31
+ "version": "5.9.2",
32
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
33
+ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
34
+ "license": "Apache-2.0",
35
+ "peer": true,
36
+ "bin": {
37
+ "tsc": "bin/tsc",
38
+ "tsserver": "bin/tsserver"
39
+ },
40
+ "engines": {
41
+ "node": ">=14.17"
42
+ }
43
+ },
44
+ "node_modules/wireql-client": {
45
+ "version": "1.0.3",
46
+ "resolved": "https://registry.npmjs.org/wireql-client/-/wireql-client-1.0.3.tgz",
47
+ "integrity": "sha512-qHCV0s+QSPEVrg4QXFewW2gPqAunuF7QdEX3Q1mcWr7FpSue6WRendyjRyr/u2vOEKuucF052vf41/dpmgLh8A==",
48
+ "license": "MIT",
49
+ "dependencies": {
50
+ "@msgpack/msgpack": "^3.0.0",
51
+ "eventemitter3": "^5.0.1",
52
+ "ws": "^8.16.0"
53
+ },
54
+ "engines": {
55
+ "node": ">=16.0.0"
56
+ },
57
+ "peerDependencies": {
58
+ "typescript": ">=4.5.0"
59
+ }
60
+ },
61
+ "node_modules/wireql-client/node_modules/@msgpack/msgpack": {
62
+ "version": "3.0.0",
63
+ "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.0.0.tgz",
64
+ "integrity": "sha512-s/OZQ1QUtSYr9tgFZh4HSFLvTR2o81r0zfQj7pClC7oFUqZaAgkQ+vADV9JBioJLK9lJoAjBEhuPhVuOIJnbhg==",
65
+ "license": "ISC",
66
+ "engines": {
67
+ "node": ">= 18"
68
+ }
69
+ },
70
+ "node_modules/ws": {
71
+ "version": "8.18.3",
72
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
73
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
74
+ "license": "MIT",
75
+ "engines": {
76
+ "node": ">=10.0.0"
77
+ },
78
+ "peerDependencies": {
79
+ "bufferutil": "^4.0.1",
80
+ "utf-8-validate": ">=5.0.2"
81
+ },
82
+ "peerDependenciesMeta": {
83
+ "bufferutil": {
84
+ "optional": true
85
+ },
86
+ "utf-8-validate": {
87
+ "optional": true
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "test-vulnerability-update-needed-across-two-versions",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "dependencies": {
10
+ "@msgpack/msgpack": "^2.7.2",
11
+ "wireql-client": "^1.0.3"
12
+ }
13
+ }
@@ -0,0 +1,21 @@
1
+ const path = require("path");
2
+ const fs = require("fs");
3
+
4
+ module.exports = {
5
+ loadFixture: (fixturePath) =>
6
+ fs.readFileSync(path.join(__dirname, "fixtures", fixturePath)).toString(),
7
+
8
+ copyDependencies: (sourceDir, destDir) => {
9
+ const srcPackageJson = path.join(
10
+ __dirname,
11
+ `fixtures/${sourceDir}/package.json`
12
+ );
13
+ fs.copyFileSync(srcPackageJson, `${destDir}/package.json`);
14
+
15
+ const srcLockfile = path.join(
16
+ __dirname,
17
+ `fixtures/${sourceDir}/package-lock.json`
18
+ );
19
+ fs.copyFileSync(srcLockfile, `${destDir}/package-lock.json`);
20
+ },
21
+ };
@@ -0,0 +1,85 @@
1
+ const path = require("path");
2
+ const os = require("os");
3
+ const fs = require("fs");
4
+ const {
5
+ findVulnerableDependencies,
6
+ } = require("../../lib/npm/vulnerability-auditor");
7
+ const helpers = require("./helpers");
8
+
9
+ describe("findVulnerableDependencies", () => {
10
+ let tempDir;
11
+ beforeEach(() => {
12
+ tempDir = fs.mkdtempSync(os.tmpdir() + path.sep);
13
+ });
14
+ afterEach(() => fs.rm(tempDir, { recursive: true }, () => {}));
15
+
16
+ it("finds vulnerable dependencies", async () => {
17
+ helpers.copyDependencies("vulnerability-auditor/simple", tempDir);
18
+
19
+ const advisories = [{
20
+ dependency_name: "@dependabot-fixtures/npm-parent-dependency",
21
+ affected_versions: [
22
+ ">= 0, < 2.0.2",
23
+ ]
24
+ }];
25
+ const actual = await findVulnerableDependencies(tempDir, advisories);
26
+ const expected = {
27
+ dependency_name: "@dependabot-fixtures/npm-parent-dependency",
28
+ fix_updates: [
29
+ {
30
+ dependency_name: "@dependabot-fixtures/npm-parent-dependency",
31
+ current_version: "2.0.0",
32
+ top_level_ancestors: [],
33
+ target_version: "2.0.2"
34
+ },
35
+ ],
36
+ top_level_ancestors: [
37
+ "@dependabot-fixtures/npm-parent-dependency"
38
+ ],
39
+ current_version: "2.0.0",
40
+ fix_available: true,
41
+ target_version: "2.0.2"
42
+ };
43
+ expect(actual).toEqual(expected);
44
+ });
45
+
46
+ it("finds vulnerable dependencies when multiple versions of the same package are affected", async () => {
47
+ helpers.copyDependencies("vulnerability-auditor/update-needed-across-two-versions", tempDir);
48
+
49
+ const advisories = [{
50
+ dependency_name: "@msgpack/msgpack",
51
+ affected_versions: [
52
+ ">= 2.0.0, < 2.8.0",
53
+ ">= 3.0.0, < 3.1.2"
54
+ ]
55
+ }];
56
+ const actual = await findVulnerableDependencies(tempDir, advisories);
57
+ const expected = {
58
+ dependency_name: "@msgpack/msgpack",
59
+ fix_updates: [
60
+ {
61
+ dependency_name: "@msgpack/msgpack",
62
+ current_version: "2.7.2",
63
+ top_level_ancestors: [],
64
+ target_version: "2.8.0"
65
+ },
66
+ {
67
+ dependency_name: "@msgpack/msgpack",
68
+ current_version: "3.0.0",
69
+ top_level_ancestors: [
70
+ "wireql-client"
71
+ ],
72
+ target_version: "3.1.2"
73
+ }
74
+ ],
75
+ top_level_ancestors: [
76
+ "@msgpack/msgpack",
77
+ "wireql-client"
78
+ ],
79
+ current_version: "2.7.2",
80
+ fix_available: true,
81
+ target_version: "2.8.0"
82
+ };
83
+ expect(actual).toEqual(expected);
84
+ });
85
+ });
@@ -267,14 +267,21 @@ module Dependabot
267
267
  # NOTE: Needs to be explicitly run through corepack to respect the
268
268
  # `packageManager` setting in `package.json`, because corepack does not
269
269
  # add shims for NPM.
270
- sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
271
- def self.run_npm_command(command, fingerprint: command)
270
+ sig do
271
+ params(
272
+ command: String,
273
+ fingerprint: T.nilable(String),
274
+ env: T.nilable(T::Hash[String, String])
275
+ ).returns(String)
276
+ end
277
+ def self.run_npm_command(command, fingerprint: command, env: nil)
272
278
  if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
273
279
  package_manager_run_command(
274
280
  NpmPackageManager::NAME,
275
281
  command,
276
282
  fingerprint: fingerprint,
277
- output_observer: ->(output) { command_observer(output) }
283
+ output_observer: ->(output) { command_observer(output) },
284
+ env: env
278
285
  )
279
286
  else
280
287
  Dependabot::SharedHelpers.run_shell_command(
@@ -506,14 +513,16 @@ module Dependabot
506
513
  name: String,
507
514
  command: String,
508
515
  fingerprint: T.nilable(String),
509
- output_observer: CommandHelpers::OutputObserver
516
+ output_observer: CommandHelpers::OutputObserver,
517
+ env: T.nilable(T::Hash[String, String])
510
518
  ).returns(String)
511
519
  end
512
520
  def self.package_manager_run_command(
513
521
  name,
514
522
  command,
515
523
  fingerprint: nil,
516
- output_observer: nil
524
+ output_observer: nil,
525
+ env: nil
517
526
  )
518
527
  return run_bun_command(command, fingerprint: fingerprint) if name == BunPackageManager::NAME
519
528
 
@@ -524,7 +533,8 @@ module Dependabot
524
533
  return Dependabot::SharedHelpers.run_shell_command(
525
534
  full_command,
526
535
  fingerprint: fingerprint,
527
- output_observer: output_observer
536
+ output_observer: output_observer,
537
+ env: env
528
538
  ).strip
529
539
  else
530
540
  Dependabot::SharedHelpers.run_shell_command(full_command, fingerprint: fingerprint)
@@ -828,9 +828,10 @@ module Dependabot
828
828
  ).returns(T.nilable(T.any(T::Hash[String, T.untyped], String, T::Array[T::Hash[String, T.untyped]])))
829
829
  end
830
830
  def run_npm8_checker(version:)
831
+ env = corepack_registry_override_env
831
832
  cmd =
832
833
  "install #{version_install_arg(version: version)} --package-lock-only --dry-run=true --ignore-scripts"
833
- output = Helpers.run_npm_command(cmd)
834
+ output = Helpers.run_npm_command(cmd, env: env)
834
835
  if output.match?(NPM8_PEER_DEP_ERROR_REGEX)
835
836
  error_context = { command: cmd, process_exit_value: 1 }
836
837
  raise SharedHelpers::HelperSubprocessFailed.new(message: output, error_context: error_context)
@@ -839,6 +840,19 @@ module Dependabot
839
840
  raise if e.message.match?(NPM8_PEER_DEP_ERROR_REGEX)
840
841
  end
841
842
 
843
+ sig { returns(T.nilable(T::Hash[String, String])) }
844
+ def corepack_registry_override_env
845
+ return nil unless Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
846
+
847
+ replaces_base_cred = credentials.find { |cred| cred["type"] == "npm_registry" && cred.replaces_base? }
848
+ registry_url = replaces_base_cred&.[]("registry")
849
+ return nil unless registry_url
850
+
851
+ registry_url = "https://#{registry_url}" unless registry_url.start_with?("http")
852
+
853
+ { "npm_config_registry" => registry_url }
854
+ end
855
+
842
856
  sig do
843
857
  params(
844
858
  version: T.nilable(T.any(String, Gem::Version))
@@ -259,6 +259,7 @@ module Dependabot
259
259
  end
260
260
 
261
261
  # rubocop:disable Metrics/AbcSize
262
+ # rubocop:disable Metrics/PerceivedComplexity
262
263
  sig { returns(T::Array[Dependabot::Dependency]) }
263
264
  def conflicting_updated_dependencies
264
265
  top_level_dependencies = top_level_dependency_lookup
@@ -266,7 +267,11 @@ module Dependabot
266
267
  updated_deps = []
267
268
  vulnerability_audit["fix_updates"].each do |update|
268
269
  dependency_name = update["dependency_name"]
269
- requirements = top_level_dependencies[dependency_name]&.requirements || []
270
+ requirements = if top_level_dependencies[dependency_name]&.version == update["current_version"]
271
+ top_level_dependencies[dependency_name]&.requirements || []
272
+ else
273
+ []
274
+ end
270
275
 
271
276
  updated_deps << build_updated_dependency(
272
277
  dependency: Dependency.new(
@@ -299,6 +304,7 @@ module Dependabot
299
304
  updated_deps.select { |dep| dep.name == dependency.name } +
300
305
  updated_deps.reject { |dep| dep.name == dependency.name }
301
306
  end
307
+ # rubocop:enable Metrics/PerceivedComplexity
302
308
 
303
309
  sig { returns(T::Hash[String, Dependabot::Dependency]) }
304
310
  def top_level_dependency_lookup
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-npm_and_yarn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.326.0
4
+ version: 0.327.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.326.0
18
+ version: 0.327.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.326.0
25
+ version: 0.327.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -269,6 +269,12 @@ files:
269
269
  - helpers/package.json
270
270
  - helpers/patches/npm++pacote+9.5.12.patch
271
271
  - helpers/run.js
272
+ - helpers/test/npm/fixtures/vulnerability-auditor/simple/package-lock.json
273
+ - helpers/test/npm/fixtures/vulnerability-auditor/simple/package.json
274
+ - helpers/test/npm/fixtures/vulnerability-auditor/update-needed-across-two-versions/package-lock.json
275
+ - helpers/test/npm/fixtures/vulnerability-auditor/update-needed-across-two-versions/package.json
276
+ - helpers/test/npm/helpers.js
277
+ - helpers/test/npm/vulnerability-auditor.test.js
272
278
  - helpers/test/npm6/conflicting-dependency-parser.test.js
273
279
  - helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package-lock.json
274
280
  - helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package.json
@@ -356,7 +362,7 @@ licenses:
356
362
  - MIT
357
363
  metadata:
358
364
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
359
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.326.0
365
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.327.0
360
366
  rdoc_options: []
361
367
  require_paths:
362
368
  - lib