dependabot-npm_and_yarn 0.388.0 → 0.389.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: f40ec37d2f3b63d9c8a3f0484174fbb11a11f115d1e74646c130ae9e4577d70e
4
- data.tar.gz: ad4b4183265d52c0c40da40cfc6c0e5eea2b7bdbe6256a07a6ca875274895def
3
+ metadata.gz: 80e087cf2994270397c5d88d6787287c102c94c0dbcca346557b7ccb97305a88
4
+ data.tar.gz: 981372aadefc57be352b2a6b15eee6edb1aa6db8e3e9adf880f6e492bd7d19ae
5
5
  SHA512:
6
- metadata.gz: f6d471d55e12b7fa3cd3e3742f09ea8ee376db3d0fe1324bc88e6a6372451d9fc4c225ae60a9e0c4aa6952fb4bcae7a82fbc9a7852d6171105a0523050dbef97
7
- data.tar.gz: e7f31e3549ff1463a774486995863b9352f99a55116b75336954be3599ce2bdbb795da6c89bcc1909582953e3538c3ddcd77bc699f3ac9b327ca091e822ada84
6
+ metadata.gz: 1442150f90c0d5d0012fde492db827f1c389cf64b2edea55fa63cbef85c86f0a48a2f8f74afc7380984c0e4bc88c72717cce8275cad3a08d1c4a0d2f80c0a372
7
+ data.tar.gz: 1c176a13cf64688ea20b7530eec0e0e53e03c0abe27ffe175a44c7e8fe80e5720f3f5ea143f497ab9130e4d9253ee74ef5825881d69095c0a3d3011fdf1b07ab
@@ -33,6 +33,7 @@ import { exec as execCb } from "child_process";
33
33
  import fs from "fs";
34
34
  import path from "path";
35
35
  import ini from "ini";
36
+ import semver from "semver";
36
37
 
37
38
  const exec = promisify(execCb);
38
39
 
@@ -259,12 +260,46 @@ export async function findVulnerableDependencies(
259
260
  delete update.dependency_location; // Not needed in the output.
260
261
  }
261
262
 
263
+ const hasDowngrade =
264
+ isVersionDowngrade(response.current_version, response.target_version) ||
265
+ response.fix_updates.some((update) =>
266
+ isVersionDowngrade(update.current_version, update.target_version)
267
+ );
268
+
269
+ if (hasDowngrade) {
270
+ response.blocking_dependencies = extractBlockingDependencies(vuln, name);
271
+ }
272
+
262
273
  return response;
263
274
  } finally {
264
275
  await stopAuditServer(server);
265
276
  }
266
277
  }
267
278
 
279
+ function isVersionDowngrade(
280
+ currentVersion?: string,
281
+ targetVersion?: string
282
+ ): boolean {
283
+ if (!currentVersion || !targetVersion) {
284
+ return false;
285
+ }
286
+
287
+ // Parse as exact semver first so prerelease identifiers (e.g. 1.0.0-beta.2
288
+ // vs 1.0.0-beta.1) are preserved; `semver.coerce` strips them and would
289
+ // treat such a downgrade as no change. Only fall back to coercion for
290
+ // nonstandard version strings that don't parse as valid semver.
291
+ const current =
292
+ semver.parse(currentVersion, { loose: true }) ??
293
+ semver.coerce(currentVersion);
294
+ const target =
295
+ semver.parse(targetVersion, { loose: true }) ?? semver.coerce(targetVersion);
296
+ if (!current || !target) {
297
+ return false;
298
+ }
299
+
300
+ return semver.gt(current, target);
301
+ }
302
+
268
303
  function convertAdvisoriesToRegistryBulkFormat(
269
304
  advisories: Advisory[]
270
305
  ): Record<string, BulkAdvisoryEntry[]> {
@@ -65,6 +65,10 @@ class LightweightInstall extends (Install as any) {
65
65
  }
66
66
  }
67
67
 
68
- export const LOCKFILE_ENTRY_REGEX = /^(.*)@([^@]*?)$/;
68
+ // Matches a yarn lockfile entry key, correctly handling:
69
+ // - scoped packages: @scope/name@requirement
70
+ // - unscoped packages: name@requirement
71
+ // - git URLs with credentials: name@https://token@host/path (@ preserved in requirement)
72
+ export const LOCKFILE_ENTRY_REGEX = /^(@[^@]+|[^@]+)@(.*)$/;
69
73
 
70
74
  export { LightweightAdd, LightweightInstall };
@@ -6,6 +6,7 @@ const stringify =
6
6
  require("@dependabot/yarn-lib/lib/lockfile/stringify").default;
7
7
 
8
8
  import type { LockfileEntry } from "./lockfile-parser.js";
9
+ import { LOCKFILE_ENTRY_REGEX } from "./helpers.js";
9
10
 
10
11
  // Get an array of a dependency's requested version ranges from a lockfile
11
12
  function getRequestedVersions(
@@ -13,9 +14,7 @@ function getRequestedVersions(
13
14
  lockfileJson: Record<string, LockfileEntry>
14
15
  ): string[] {
15
16
  const requestedVersions: string[] = [];
16
- // Matching dependency name and version requirements which could be a full url:
17
- // dep@version, @private-dep@version, private-dep@https:://token@gh.com...#ref
18
- const re = /^(.[^@]*)@(.*?)$/;
17
+ const re = LOCKFILE_ENTRY_REGEX;
19
18
 
20
19
  Object.entries(lockfileJson).forEach(([name]) => {
21
20
  if (name.match(re)) {
@@ -878,6 +878,14 @@
878
878
  "node": "^20.19.0 || ^22.13.0 || >=24"
879
879
  }
880
880
  },
881
+ "node_modules/@gar/promise-retry": {
882
+ "version": "1.0.3",
883
+ "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz",
884
+ "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==",
885
+ "engines": {
886
+ "node": "^20.17.0 || >=22.9.0"
887
+ }
888
+ },
881
889
  "node_modules/@humanfs/core": {
882
890
  "version": "0.19.1",
883
891
  "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -3194,25 +3202,25 @@
3194
3202
  }
3195
3203
  },
3196
3204
  "node_modules/@sigstore/sign": {
3197
- "version": "4.1.0",
3198
- "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz",
3199
- "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==",
3205
+ "version": "4.1.1",
3206
+ "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz",
3207
+ "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==",
3200
3208
  "dependencies": {
3209
+ "@gar/promise-retry": "^1.0.2",
3201
3210
  "@sigstore/bundle": "^4.0.0",
3202
- "@sigstore/core": "^3.1.0",
3211
+ "@sigstore/core": "^3.2.0",
3203
3212
  "@sigstore/protobuf-specs": "^0.5.0",
3204
- "make-fetch-happen": "^15.0.3",
3205
- "proc-log": "^6.1.0",
3206
- "promise-retry": "^2.0.1"
3213
+ "make-fetch-happen": "^15.0.4",
3214
+ "proc-log": "^6.1.0"
3207
3215
  },
3208
3216
  "engines": {
3209
3217
  "node": "^20.17.0 || >=22.9.0"
3210
3218
  }
3211
3219
  },
3212
3220
  "node_modules/@sigstore/tuf": {
3213
- "version": "4.0.1",
3214
- "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz",
3215
- "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==",
3221
+ "version": "4.0.2",
3222
+ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz",
3223
+ "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==",
3216
3224
  "dependencies": {
3217
3225
  "@sigstore/protobuf-specs": "^0.5.0",
3218
3226
  "tuf-js": "^4.1.0"
@@ -3287,9 +3295,9 @@
3287
3295
  }
3288
3296
  },
3289
3297
  "node_modules/@tufjs/models/node_modules/brace-expansion": {
3290
- "version": "5.0.5",
3291
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
3292
- "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
3298
+ "version": "5.0.7",
3299
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
3300
+ "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
3293
3301
  "dependencies": {
3294
3302
  "balanced-match": "^4.0.2"
3295
3303
  },
@@ -3298,11 +3306,11 @@
3298
3306
  }
3299
3307
  },
3300
3308
  "node_modules/@tufjs/models/node_modules/minimatch": {
3301
- "version": "10.2.4",
3302
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
3303
- "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
3309
+ "version": "10.2.5",
3310
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
3311
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
3304
3312
  "dependencies": {
3305
- "brace-expansion": "^5.0.2"
3313
+ "brace-expansion": "^5.0.5"
3306
3314
  },
3307
3315
  "engines": {
3308
3316
  "node": "18 || 20 || >=22"
@@ -6549,11 +6557,10 @@
6549
6557
  }
6550
6558
  },
6551
6559
  "node_modules/handlebars": {
6552
- "version": "4.7.8",
6553
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
6554
- "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
6560
+ "version": "4.7.9",
6561
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
6562
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
6555
6563
  "dev": true,
6556
- "license": "MIT",
6557
6564
  "dependencies": {
6558
6565
  "minimist": "^1.2.5",
6559
6566
  "neo-async": "^2.6.2",
@@ -9490,9 +9497,9 @@
9490
9497
  }
9491
9498
  },
9492
9499
  "node_modules/lodash": {
9493
- "version": "4.17.23",
9494
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
9495
- "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
9500
+ "version": "4.18.1",
9501
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
9502
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
9496
9503
  },
9497
9504
  "node_modules/lodash.clone": {
9498
9505
  "version": "4.5.0",
@@ -9563,11 +9570,13 @@
9563
9570
  "license": "ISC"
9564
9571
  },
9565
9572
  "node_modules/make-fetch-happen": {
9566
- "version": "15.0.3",
9567
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz",
9568
- "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==",
9573
+ "version": "15.0.6",
9574
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz",
9575
+ "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==",
9569
9576
  "dependencies": {
9577
+ "@gar/promise-retry": "^1.0.0",
9570
9578
  "@npmcli/agent": "^4.0.0",
9579
+ "@npmcli/redact": "^4.0.0",
9571
9580
  "cacache": "^20.0.1",
9572
9581
  "http-cache-semantics": "^4.1.1",
9573
9582
  "minipass": "^7.0.2",
@@ -9576,7 +9585,6 @@
9576
9585
  "minipass-pipeline": "^1.2.4",
9577
9586
  "negotiator": "^1.0.0",
9578
9587
  "proc-log": "^6.0.0",
9579
- "promise-retry": "^2.0.1",
9580
9588
  "ssri": "^13.0.0"
9581
9589
  },
9582
9590
  "engines": {
@@ -15641,16 +15649,16 @@
15641
15649
  "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
15642
15650
  },
15643
15651
  "node_modules/sigstore": {
15644
- "version": "4.1.0",
15645
- "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz",
15646
- "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==",
15652
+ "version": "4.1.1",
15653
+ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz",
15654
+ "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==",
15647
15655
  "dependencies": {
15648
15656
  "@sigstore/bundle": "^4.0.0",
15649
- "@sigstore/core": "^3.1.0",
15657
+ "@sigstore/core": "^3.2.1",
15650
15658
  "@sigstore/protobuf-specs": "^0.5.0",
15651
- "@sigstore/sign": "^4.1.0",
15652
- "@sigstore/tuf": "^4.0.1",
15653
- "@sigstore/verify": "^3.1.0"
15659
+ "@sigstore/sign": "^4.1.1",
15660
+ "@sigstore/tuf": "^4.0.2",
15661
+ "@sigstore/verify": "^3.1.1"
15654
15662
  },
15655
15663
  "engines": {
15656
15664
  "node": "^20.17.0 || >=22.9.0"
@@ -17627,6 +17635,11 @@
17627
17635
  "levn": "^0.4.1"
17628
17636
  }
17629
17637
  },
17638
+ "@gar/promise-retry": {
17639
+ "version": "1.0.3",
17640
+ "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz",
17641
+ "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA=="
17642
+ },
17630
17643
  "@humanfs/core": {
17631
17644
  "version": "0.19.1",
17632
17645
  "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -19278,22 +19291,22 @@
19278
19291
  "integrity": "sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA=="
19279
19292
  },
19280
19293
  "@sigstore/sign": {
19281
- "version": "4.1.0",
19282
- "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz",
19283
- "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==",
19294
+ "version": "4.1.1",
19295
+ "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz",
19296
+ "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==",
19284
19297
  "requires": {
19298
+ "@gar/promise-retry": "^1.0.2",
19285
19299
  "@sigstore/bundle": "^4.0.0",
19286
- "@sigstore/core": "^3.1.0",
19300
+ "@sigstore/core": "^3.2.0",
19287
19301
  "@sigstore/protobuf-specs": "^0.5.0",
19288
- "make-fetch-happen": "^15.0.3",
19289
- "proc-log": "^6.1.0",
19290
- "promise-retry": "^2.0.1"
19302
+ "make-fetch-happen": "^15.0.4",
19303
+ "proc-log": "^6.1.0"
19291
19304
  }
19292
19305
  },
19293
19306
  "@sigstore/tuf": {
19294
- "version": "4.0.1",
19295
- "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz",
19296
- "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==",
19307
+ "version": "4.0.2",
19308
+ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz",
19309
+ "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==",
19297
19310
  "requires": {
19298
19311
  "@sigstore/protobuf-specs": "^0.5.0",
19299
19312
  "tuf-js": "^4.1.0"
@@ -19353,19 +19366,19 @@
19353
19366
  "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="
19354
19367
  },
19355
19368
  "brace-expansion": {
19356
- "version": "5.0.5",
19357
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
19358
- "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
19369
+ "version": "5.0.7",
19370
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
19371
+ "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
19359
19372
  "requires": {
19360
19373
  "balanced-match": "^4.0.2"
19361
19374
  }
19362
19375
  },
19363
19376
  "minimatch": {
19364
- "version": "10.2.4",
19365
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
19366
- "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
19377
+ "version": "10.2.5",
19378
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
19379
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
19367
19380
  "requires": {
19368
- "brace-expansion": "^5.0.2"
19381
+ "brace-expansion": "^5.0.5"
19369
19382
  }
19370
19383
  }
19371
19384
  }
@@ -21699,9 +21712,9 @@
21699
21712
  }
21700
21713
  },
21701
21714
  "handlebars": {
21702
- "version": "4.7.8",
21703
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
21704
- "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
21715
+ "version": "4.7.9",
21716
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
21717
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
21705
21718
  "dev": true,
21706
21719
  "requires": {
21707
21720
  "minimist": "^1.2.5",
@@ -23868,9 +23881,9 @@
23868
23881
  }
23869
23882
  },
23870
23883
  "lodash": {
23871
- "version": "4.17.23",
23872
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
23873
- "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
23884
+ "version": "4.18.1",
23885
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
23886
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
23874
23887
  },
23875
23888
  "lodash.clone": {
23876
23889
  "version": "4.5.0",
@@ -23927,11 +23940,13 @@
23927
23940
  "dev": true
23928
23941
  },
23929
23942
  "make-fetch-happen": {
23930
- "version": "15.0.3",
23931
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz",
23932
- "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==",
23943
+ "version": "15.0.6",
23944
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz",
23945
+ "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==",
23933
23946
  "requires": {
23947
+ "@gar/promise-retry": "^1.0.0",
23934
23948
  "@npmcli/agent": "^4.0.0",
23949
+ "@npmcli/redact": "^4.0.0",
23935
23950
  "cacache": "^20.0.1",
23936
23951
  "http-cache-semantics": "^4.1.1",
23937
23952
  "minipass": "^7.0.2",
@@ -23940,7 +23955,6 @@
23940
23955
  "minipass-pipeline": "^1.2.4",
23941
23956
  "negotiator": "^1.0.0",
23942
23957
  "proc-log": "^6.0.0",
23943
- "promise-retry": "^2.0.1",
23944
23958
  "ssri": "^13.0.0"
23945
23959
  },
23946
23960
  "dependencies": {
@@ -28446,16 +28460,16 @@
28446
28460
  "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
28447
28461
  },
28448
28462
  "sigstore": {
28449
- "version": "4.1.0",
28450
- "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz",
28451
- "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==",
28463
+ "version": "4.1.1",
28464
+ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz",
28465
+ "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==",
28452
28466
  "requires": {
28453
28467
  "@sigstore/bundle": "^4.0.0",
28454
- "@sigstore/core": "^3.1.0",
28468
+ "@sigstore/core": "^3.2.1",
28455
28469
  "@sigstore/protobuf-specs": "^0.5.0",
28456
- "@sigstore/sign": "^4.1.0",
28457
- "@sigstore/tuf": "^4.0.1",
28458
- "@sigstore/verify": "^3.1.0"
28470
+ "@sigstore/sign": "^4.1.1",
28471
+ "@sigstore/tuf": "^4.0.2",
28472
+ "@sigstore/verify": "^3.1.1"
28459
28473
  }
28460
28474
  },
28461
28475
  "slash": {
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "locked-transitive-dependency",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 2,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "locked-transitive-dependency",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "@dependabot-fixtures/npm-parent-dependency": "2.0.0"
13
+ }
14
+ },
15
+ "node_modules/@dependabot-fixtures/npm-intermediate-dependency": {
16
+ "version": "0.0.1",
17
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-intermediate-dependency/-/npm-intermediate-dependency-0.0.1.tgz",
18
+ "integrity": "sha512-/N77Dzpfg8BIfFgpJrMk86ueUYTVhmpc4RobuHpIpKSc3GZr4Ltu4au92brnUGk66UkzgrMmtgqRXO8OrOspKQ==",
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
+ "dependencies": {
28
+ "@dependabot-fixtures/npm-intermediate-dependency": "0.0.1"
29
+ }
30
+ },
31
+ "node_modules/@dependabot-fixtures/npm-transitive-dependency": {
32
+ "version": "1.0.0",
33
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-transitive-dependency/-/npm-transitive-dependency-1.0.0.tgz",
34
+ "integrity": "sha512-nFbzQH0TRgdzSA2/FH6MPnxZDpD+5Bgz00aD5Edgbc1wY/k8VC9s7lnk22dBTgJLwoY7MgbrnAf9rAvN08hHVg=="
35
+ }
36
+ },
37
+ "dependencies": {
38
+ "@dependabot-fixtures/npm-intermediate-dependency": {
39
+ "version": "0.0.1",
40
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-intermediate-dependency/-/npm-intermediate-dependency-0.0.1.tgz",
41
+ "integrity": "sha512-/N77Dzpfg8BIfFgpJrMk86ueUYTVhmpc4RobuHpIpKSc3GZr4Ltu4au92brnUGk66UkzgrMmtgqRXO8OrOspKQ==",
42
+ "requires": {
43
+ "@dependabot-fixtures/npm-transitive-dependency": "1.0.0"
44
+ }
45
+ },
46
+ "@dependabot-fixtures/npm-parent-dependency": {
47
+ "version": "2.0.0",
48
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-parent-dependency/-/npm-parent-dependency-2.0.0.tgz",
49
+ "integrity": "sha512-5LtLEL1yzO2TdkNX3R9cvr+nKmhw5h4xM0wkFTJeK14wxlI9d8gEYA+I2hUi+IP96ucBSztAnOgZVwoJHEZb6A==",
50
+ "requires": {
51
+ "@dependabot-fixtures/npm-intermediate-dependency": "0.0.1"
52
+ }
53
+ },
54
+ "@dependabot-fixtures/npm-transitive-dependency": {
55
+ "version": "1.0.0",
56
+ "resolved": "https://registry.npmjs.org/@dependabot-fixtures/npm-transitive-dependency/-/npm-transitive-dependency-1.0.0.tgz",
57
+ "integrity": "sha512-nFbzQH0TRgdzSA2/FH6MPnxZDpD+5Bgz00aD5Edgbc1wY/k8VC9s7lnk22dBTgJLwoY7MgbrnAf9rAvN08hHVg=="
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "locked-transitive-dependency",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "@dependabot-fixtures/npm-parent-dependency": "2.0.0"
14
+ }
15
+ }
@@ -313,4 +313,39 @@ describe("findVulnerableDependencies", () => {
313
313
  ])
314
314
  );
315
315
  });
316
+
317
+ it("reports blocking dependencies when a successful fix path includes a downgrade", async () => {
318
+ helpers.copyDependenciesTree(
319
+ "vulnerability-auditor/locked-transitive-dependency",
320
+ tempDir
321
+ );
322
+
323
+ const advisories = [
324
+ {
325
+ dependency_name: "@dependabot-fixtures/npm-transitive-dependency",
326
+ affected_versions: [">= 0"],
327
+ },
328
+ ];
329
+ const actual = await findVulnerableDependencies(tempDir, advisories);
330
+
331
+ expect(actual.fix_available).toBe(true);
332
+ expect(actual.fix_updates).toEqual(
333
+ expect.arrayContaining([
334
+ expect.objectContaining({
335
+ dependency_name: "@dependabot-fixtures/npm-parent-dependency",
336
+ current_version: "2.0.0",
337
+ target_version: "1.0.0",
338
+ }),
339
+ ])
340
+ );
341
+ expect(actual.blocking_dependencies).toEqual(
342
+ expect.arrayContaining([
343
+ expect.objectContaining({
344
+ name: "@dependabot-fixtures/npm-intermediate-dependency",
345
+ requirement: "1.0.0",
346
+ top_level_ancestor: "@dependabot-fixtures/npm-parent-dependency",
347
+ }),
348
+ ])
349
+ );
350
+ });
316
351
  });
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "test-project",
3
+ "version": "1.0.0",
4
+ "dependencies": {
5
+ "is-positive": "^3.0.0"
6
+ }
7
+ }
@@ -0,0 +1,8 @@
1
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ # yarn lockfile v1
3
+
4
+
5
+ "is-positive@^3.0.0", "is-positive@3.0.0":
6
+ version "3.0.0"
7
+ resolved "https://registry.yarnpkg.com/is-positive/-/is-positive-3.0.0.tgz#e1ee21cb67a4b41ea3e9ca23b32e6fb51bef9d26"
8
+ integrity sha512-3aX3F8v8gzxT1DnLXo8/0fQ9i/aKDqgDZZvFh/hhsb0HkYfNxz5j9xLF8f3T8L/5DgVxWlBGFbHfgHYf3vJXEA==
@@ -0,0 +1,8 @@
1
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ # yarn lockfile v1
3
+
4
+
5
+ "is-positive@^3.0.0", "is-positive@3.1.0":
6
+ version "3.1.0"
7
+ resolved "https://registry.yarnpkg.com/is-positive/-/is-positive-3.1.0.tgz#857db584a1ba5d1cb2980527fc3b6c435d37b0fd"
8
+ integrity sha512-+U/XpRU56FtaS3j2kYi0V5xsZCKI3bk+GcUPx8yDQWBmXGPjfLBHOUUh3Xmtr1O78+B3gchX1oGdnRPxfEUJFg==
@@ -0,0 +1,40 @@
1
+ import { LOCKFILE_ENTRY_REGEX } from "../../lib/yarn/helpers.js";
2
+
3
+ describe("LOCKFILE_ENTRY_REGEX", () => {
4
+ it("matches a simple unscoped package", () => {
5
+ const match = "left-pad@1.0.0".match(LOCKFILE_ENTRY_REGEX);
6
+ expect(match).not.toBeNull();
7
+ const [, packageName, requirement] = match!;
8
+ expect(packageName).toBe("left-pad");
9
+ expect(requirement).toBe("1.0.0");
10
+ });
11
+
12
+ it("matches a scoped package", () => {
13
+ const match = "@scope/pkg@1.2.3".match(LOCKFILE_ENTRY_REGEX);
14
+ expect(match).not.toBeNull();
15
+ const [, packageName, requirement] = match!;
16
+ expect(packageName).toBe("@scope/pkg");
17
+ expect(requirement).toBe("1.2.3");
18
+ });
19
+
20
+ it("matches an unscoped package with a git URL containing @", () => {
21
+ const key =
22
+ "is-number@https://dummy-token@github.com/jonschlinkert/is-number.git#master";
23
+ const match = key.match(LOCKFILE_ENTRY_REGEX);
24
+ expect(match).not.toBeNull();
25
+ const [, packageName, requirement] = match!;
26
+ expect(packageName).toBe("is-number");
27
+ expect(requirement).toBe(
28
+ "https://dummy-token@github.com/jonschlinkert/is-number.git#master"
29
+ );
30
+ });
31
+
32
+ it("matches a scoped package with a git URL containing multiple @ characters", () => {
33
+ const key = "@scope/pkg@git+https://x@github.com/y/z";
34
+ const match = key.match(LOCKFILE_ENTRY_REGEX);
35
+ expect(match).not.toBeNull();
36
+ const [, packageName, requirement] = match!;
37
+ expect(packageName).toBe("@scope/pkg");
38
+ expect(requirement).toBe("git+https://x@github.com/y/z");
39
+ });
40
+ });
@@ -114,4 +114,32 @@ describe("updater", () => {
114
114
  );
115
115
  }
116
116
  });
117
+
118
+ it("correctly updates packages with multiple lockfile entries", async () => {
119
+ // This test verifies that replaceLockfileDeclaration correctly consolidates
120
+ // duplicate lockfile entries when updating versions. This ensures the regex
121
+ // change properly identifies all entries belonging to a dependency.
122
+ copyDependencies("scoped-git-source", tempDir);
123
+
124
+ const result = await updateDependencyFiles(tempDir, [
125
+ {
126
+ name: "is-positive",
127
+ version: "3.1.0",
128
+ requirements: [
129
+ {
130
+ requirement: "^3.0.0",
131
+ file: "package.json",
132
+ groups: ["dependencies"],
133
+ },
134
+ ],
135
+ },
136
+ ]);
137
+
138
+ // The updated lock should have the new version
139
+ expect(result["yarn.lock"]).toContain('version "3.1.0"');
140
+ // Old version should be gone
141
+ expect(result["yarn.lock"]).not.toContain('version "3.0.0"');
142
+ // The caret requirement entry should be preserved
143
+ expect(result["yarn.lock"]).toContain("is-positive@^3.0.0");
144
+ });
117
145
  });
@@ -38,7 +38,7 @@ module Dependabot
38
38
  prepare! unless prepared
39
39
 
40
40
  @dependencies.each_with_object({}) do |dep, resolved|
41
- all_versions = dep.metadata[:all_versions] || [dep]
41
+ all_versions = dep.metadata_dependencies(:all_versions) || [dep]
42
42
 
43
43
  all_versions.each do |version_dep|
44
44
  purl = build_purl(version_dep)
@@ -147,7 +147,7 @@ module Dependabot
147
147
  return unless Dependabot::Experiments.enabled?(:enable_audit_fix_fallback)
148
148
  return unless current_version
149
149
 
150
- all_versions = parsed_dep.metadata[:all_versions]
150
+ all_versions = parsed_dep.metadata_dependencies(:all_versions)
151
151
  return unless all_versions&.any?
152
152
 
153
153
  best_candidate_version(all_versions, current_version)
@@ -197,9 +197,16 @@ module Dependabot
197
197
  downgrades_version?(update["current_version"], update["target_version"])
198
198
  end
199
199
 
200
- return downgrades_dependency_message(dependency) unless downgraded_dependency
200
+ # When no individual `fix_updates` entry is itself a downgrade, the audited
201
+ # dependency's own current/target versions are the ones being downgraded.
202
+ downgraded_dependency ||= {
203
+ "dependency_name" => dependency.name,
204
+ "current_version" => audit_result["current_version"],
205
+ "target_version" => audit_result["target_version"],
206
+ "top_level_ancestors" => audit_result["top_level_ancestors"]
207
+ }
201
208
 
202
- downgraded_dependency_message(dependency, downgraded_dependency)
209
+ downgraded_dependency_message(dependency, downgraded_dependency, audit_result)
203
210
  when :fix_incomplete
204
211
  "The lockfile might be out of sync?"
205
212
  else
@@ -319,23 +326,76 @@ module Dependabot
319
326
  "update path still resolves it to #{audit_result['target_version']}"
320
327
  end
321
328
 
322
- sig { params(dependency: Dependabot::Dependency).returns(String) }
323
- def downgrades_dependency_message(dependency)
324
- "A patched version exists for #{dependency.name}, but the available " \
325
- "update path requires downgrading another dependency"
329
+ sig do
330
+ params(
331
+ dependency: Dependabot::Dependency,
332
+ downgraded_dependency: T::Hash[String, T.untyped],
333
+ audit_result: T.nilable(T::Hash[String, T.untyped])
334
+ ).returns(String)
335
+ end
336
+ def downgraded_dependency_message(dependency, downgraded_dependency, audit_result = nil)
337
+ downgraded_name = downgraded_dependency["dependency_name"]
338
+ current_version = downgraded_dependency["current_version"]
339
+ target_version = downgraded_dependency["target_version"]
340
+ top_level_ancestors = downgraded_dependency["top_level_ancestors"]
341
+
342
+ message = "A patched version exists for #{dependency.name}, but the available " \
343
+ "update path would downgrade #{downgraded_name} " \
344
+ "from #{current_version} to #{target_version}"
345
+
346
+ # `blocking_dependencies` covers every top-level package that still requires a
347
+ # vulnerable version of `dependency.name` anywhere in the project, which can include
348
+ # packages unrelated to why *this particular* dependency was downgraded. Narrow it down
349
+ # to only the edges reachable from the downgraded dependency itself so the explanation
350
+ # stays focused on the actual cause.
351
+ relevant_ancestors = ([downgraded_name] + Array(top_level_ancestors)).uniq
352
+ blockers = audit_result&.dig("blocking_dependencies")
353
+ relevant_blockers = blockers&.select { |blocker| relevant_ancestors.include?(blocker["top_level_ancestor"]) }
354
+
355
+ if relevant_blockers&.any?
356
+ details = downgrade_blocker_details(dependency.name, relevant_blockers)
357
+ message += " because:\n#{details}"
358
+ elsif top_level_ancestors&.any?
359
+ ancestors_list = top_level_ancestors.sort.map { |ancestor| " - #{ancestor}" }.join("\n")
360
+ message += " because these top-level dependencies are involved in the update path:\n#{ancestors_list}"
361
+ message += "\n\nTo resolve this, update #{top_level_ancestors.sort.join(', ')} to a release " \
362
+ "that allows #{dependency.name} to be updated to a non-vulnerable version, or add an " \
363
+ "override/resolution pinning #{dependency.name} to a non-vulnerable version."
364
+ end
365
+
366
+ message
326
367
  end
327
368
 
328
369
  sig do
329
370
  params(
330
- dependency: Dependabot::Dependency,
331
- downgraded_dependency: T::Hash[String, T.untyped]
371
+ vulnerable_dependency: String,
372
+ blockers: T::Array[T::Hash[String, T.untyped]]
332
373
  ).returns(String)
333
374
  end
334
- def downgraded_dependency_message(dependency, downgraded_dependency)
335
- "A patched version exists for #{dependency.name}, but the available " \
336
- "update path would downgrade #{downgraded_dependency['dependency_name']} " \
337
- "from #{downgraded_dependency['current_version']} to " \
338
- "#{downgraded_dependency['target_version']}"
375
+ def downgrade_blocker_details(vulnerable_dependency, blockers)
376
+ grouped_by_ancestor = blockers.group_by { |blocker| blocker["top_level_ancestor"] }
377
+
378
+ ancestor_lines = grouped_by_ancestor.sort.map do |ancestor, group|
379
+ requirements = group.map do |blocker|
380
+ blocker_name = blocker["name"]
381
+ detail = "#{vulnerable_dependency}@#{blocker['requirement']}"
382
+ detail += " (via #{blocker_name}@#{blocker['version']})" if blocker_name != ancestor
383
+ detail
384
+ end.uniq.join(" and ")
385
+
386
+ " - #{ancestor}: requires #{requirements}"
387
+ end.join("\n")
388
+
389
+ ancestors = grouped_by_ancestor.keys.sort.join(", ")
390
+ details = "The following packages currently require #{vulnerable_dependency} through these " \
391
+ "dependency edges:\n"
392
+ details += ancestor_lines
393
+ details += "\n\nThese edges help explain why npm selected a downgrade path. To resolve this, either:\n"
394
+ details += " 1. Update #{ancestors} to versions that support the patched " \
395
+ "#{vulnerable_dependency}, or\n"
396
+ details += " 2. Add an override/resolution to pin #{vulnerable_dependency} to a " \
397
+ "non-vulnerable version compatible with your dependencies"
398
+ details
339
399
  end
340
400
 
341
401
  sig { params(audit_result: T::Hash[String, T.untyped]).returns(T::Boolean) }
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.388.0
4
+ version: 0.389.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.388.0
18
+ version: 0.389.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.388.0
25
+ version: 0.389.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -277,6 +277,8 @@ files:
277
277
  - helpers/test/npm/fixtures/vulnerability-auditor/fix-removes-package/package.json
278
278
  - helpers/test/npm/fixtures/vulnerability-auditor/locked-by-parent/package-lock.json
279
279
  - helpers/test/npm/fixtures/vulnerability-auditor/locked-by-parent/package.json
280
+ - helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package-lock.json
281
+ - helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package.json
280
282
  - helpers/test/npm/fixtures/vulnerability-auditor/outdated-package-lock/package-lock.json
281
283
  - helpers/test/npm/fixtures/vulnerability-auditor/outdated-package-lock/package.json
282
284
  - helpers/test/npm/fixtures/vulnerability-auditor/simple/package-lock.json
@@ -318,9 +320,13 @@ files:
318
320
  - helpers/test/yarn/fixtures/updater/illegal_character/yarn.lock
319
321
  - helpers/test/yarn/fixtures/updater/original/package.json
320
322
  - helpers/test/yarn/fixtures/updater/original/yarn.lock
323
+ - helpers/test/yarn/fixtures/updater/scoped-git-source-updated/yarn.lock
324
+ - helpers/test/yarn/fixtures/updater/scoped-git-source/package.json
325
+ - helpers/test/yarn/fixtures/updater/scoped-git-source/yarn.lock
321
326
  - helpers/test/yarn/fixtures/updater/updated/yarn.lock
322
327
  - helpers/test/yarn/fixtures/updater/with-version-comments/package.json
323
328
  - helpers/test/yarn/fixtures/updater/with-version-comments/yarn.lock
329
+ - helpers/test/yarn/helpers.test.ts
324
330
  - helpers/test/yarn/helpers.ts
325
331
  - helpers/test/yarn/updater.test.ts
326
332
  - helpers/tsconfig.build.json
@@ -381,7 +387,7 @@ licenses:
381
387
  - MIT
382
388
  metadata:
383
389
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
384
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.388.0
390
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.389.0
385
391
  rdoc_options: []
386
392
  require_paths:
387
393
  - lib