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 +4 -4
- data/helpers/lib/npm/vulnerability-auditor.ts +35 -0
- data/helpers/lib/yarn/helpers.ts +5 -1
- data/helpers/lib/yarn/replace-lockfile-declaration.ts +2 -3
- data/helpers/package-lock.json +83 -69
- data/helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package-lock.json +60 -0
- data/helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package.json +15 -0
- data/helpers/test/npm/vulnerability-auditor.test.ts +35 -0
- data/helpers/test/yarn/fixtures/updater/scoped-git-source/package.json +7 -0
- data/helpers/test/yarn/fixtures/updater/scoped-git-source/yarn.lock +8 -0
- data/helpers/test/yarn/fixtures/updater/scoped-git-source-updated/yarn.lock +8 -0
- data/helpers/test/yarn/helpers.test.ts +40 -0
- data/helpers/test/yarn/updater.test.ts +28 -0
- data/lib/dependabot/npm_and_yarn/dependency_grapher.rb +1 -1
- data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +1 -1
- data/lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb +73 -13
- metadata +10 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80e087cf2994270397c5d88d6787287c102c94c0dbcca346557b7ccb97305a88
|
|
4
|
+
data.tar.gz: 981372aadefc57be352b2a6b15eee6edb1aa6db8e3e9adf880f6e492bd7d19ae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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[]> {
|
data/helpers/lib/yarn/helpers.ts
CHANGED
|
@@ -65,6 +65,10 @@ class LightweightInstall extends (Install as any) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
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
|
-
|
|
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)) {
|
data/helpers/package-lock.json
CHANGED
|
@@ -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.
|
|
3198
|
-
"resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.
|
|
3199
|
-
"integrity": "sha512-
|
|
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.
|
|
3211
|
+
"@sigstore/core": "^3.2.0",
|
|
3203
3212
|
"@sigstore/protobuf-specs": "^0.5.0",
|
|
3204
|
-
"make-fetch-happen": "^15.0.
|
|
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.
|
|
3214
|
-
"resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.
|
|
3215
|
-
"integrity": "sha512-
|
|
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.
|
|
3291
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.
|
|
3292
|
-
"integrity": "sha512-
|
|
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.
|
|
3302
|
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.
|
|
3303
|
-
"integrity": "sha512-
|
|
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.
|
|
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.
|
|
6553
|
-
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.
|
|
6554
|
-
"integrity": "sha512-
|
|
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.
|
|
9494
|
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.
|
|
9495
|
-
"integrity": "sha512-
|
|
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.
|
|
9567
|
-
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.
|
|
9568
|
-
"integrity": "sha512-
|
|
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.
|
|
15645
|
-
"resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.
|
|
15646
|
-
"integrity": "sha512
|
|
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
|
|
15657
|
+
"@sigstore/core": "^3.2.1",
|
|
15650
15658
|
"@sigstore/protobuf-specs": "^0.5.0",
|
|
15651
|
-
"@sigstore/sign": "^4.1.
|
|
15652
|
-
"@sigstore/tuf": "^4.0.
|
|
15653
|
-
"@sigstore/verify": "^3.1.
|
|
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.
|
|
19282
|
-
"resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.
|
|
19283
|
-
"integrity": "sha512-
|
|
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.
|
|
19300
|
+
"@sigstore/core": "^3.2.0",
|
|
19287
19301
|
"@sigstore/protobuf-specs": "^0.5.0",
|
|
19288
|
-
"make-fetch-happen": "^15.0.
|
|
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.
|
|
19295
|
-
"resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.
|
|
19296
|
-
"integrity": "sha512-
|
|
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.
|
|
19357
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.
|
|
19358
|
-
"integrity": "sha512-
|
|
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.
|
|
19365
|
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.
|
|
19366
|
-
"integrity": "sha512-
|
|
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.
|
|
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.
|
|
21703
|
-
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.
|
|
21704
|
-
"integrity": "sha512-
|
|
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.
|
|
23872
|
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.
|
|
23873
|
-
"integrity": "sha512-
|
|
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.
|
|
23931
|
-
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.
|
|
23932
|
-
"integrity": "sha512-
|
|
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.
|
|
28450
|
-
"resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.
|
|
28451
|
-
"integrity": "sha512
|
|
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
|
|
28468
|
+
"@sigstore/core": "^3.2.1",
|
|
28455
28469
|
"@sigstore/protobuf-specs": "^0.5.0",
|
|
28456
|
-
"@sigstore/sign": "^4.1.
|
|
28457
|
-
"@sigstore/tuf": "^4.0.
|
|
28458
|
-
"@sigstore/verify": "^3.1.
|
|
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": {
|
data/helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package-lock.json
ADDED
|
@@ -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
|
+
}
|
data/helpers/test/npm/fixtures/vulnerability-auditor/locked-transitive-dependency/package.json
ADDED
|
@@ -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,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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
-
|
|
331
|
-
|
|
371
|
+
vulnerable_dependency: String,
|
|
372
|
+
blockers: T::Array[T::Hash[String, T.untyped]]
|
|
332
373
|
).returns(String)
|
|
333
374
|
end
|
|
334
|
-
def
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|