github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/javascript/parse_package_lock_test.go (about) 1 package javascript 2 3 import ( 4 "testing" 5 6 "github.com/anchore/syft/syft/artifact" 7 "github.com/anchore/syft/syft/file" 8 "github.com/anchore/syft/syft/pkg" 9 "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" 10 ) 11 12 func TestParsePackageLock(t *testing.T) { 13 var expectedRelationships []artifact.Relationship 14 expectedPkgs := []pkg.Package{ 15 { 16 Name: "pkg-lock", 17 Version: "0.0.0", 18 PURL: "pkg:npm/pkg-lock@0.0.0", 19 Language: pkg.JavaScript, 20 Type: pkg.NpmPkg, 21 MetadataType: "NpmPackageLockJsonMetadata", 22 Metadata: pkg.NpmPackageLockJSONMetadata{}, 23 }, 24 { 25 Name: "@actions/core", 26 Version: "1.6.0", 27 PURL: "pkg:npm/%40actions/core@1.6.0", 28 Language: pkg.JavaScript, 29 Type: pkg.NpmPkg, 30 MetadataType: "NpmPackageLockJsonMetadata", 31 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, 32 }, 33 { 34 Name: "ansi-regex", 35 Version: "3.0.0", 36 PURL: "pkg:npm/ansi-regex@3.0.0", 37 Language: pkg.JavaScript, 38 Type: pkg.NpmPkg, 39 MetadataType: "NpmPackageLockJsonMetadata", 40 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, 41 }, 42 { 43 Name: "cowsay", 44 Version: "1.4.0", 45 PURL: "pkg:npm/cowsay@1.4.0", 46 Language: pkg.JavaScript, 47 Type: pkg.NpmPkg, 48 MetadataType: "NpmPackageLockJsonMetadata", 49 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, 50 }, 51 { 52 Name: "get-stdin", 53 Version: "5.0.1", 54 PURL: "pkg:npm/get-stdin@5.0.1", 55 Language: pkg.JavaScript, 56 Type: pkg.NpmPkg, 57 MetadataType: "NpmPackageLockJsonMetadata", 58 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, 59 }, 60 { 61 Name: "is-fullwidth-code-point", 62 Version: "2.0.0", 63 PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", 64 Language: pkg.JavaScript, 65 Type: pkg.NpmPkg, 66 MetadataType: "NpmPackageLockJsonMetadata", 67 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, 68 }, 69 { 70 Name: "minimist", 71 Version: "0.0.10", 72 PURL: "pkg:npm/minimist@0.0.10", 73 Language: pkg.JavaScript, 74 Type: pkg.NpmPkg, 75 MetadataType: "NpmPackageLockJsonMetadata", 76 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, 77 }, 78 { 79 Name: "optimist", 80 Version: "0.6.1", 81 PURL: "pkg:npm/optimist@0.6.1", 82 Language: pkg.JavaScript, 83 Type: pkg.NpmPkg, 84 MetadataType: "NpmPackageLockJsonMetadata", 85 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, 86 }, 87 { 88 Name: "string-width", 89 Version: "2.1.1", 90 PURL: "pkg:npm/string-width@2.1.1", 91 Language: pkg.JavaScript, 92 Type: pkg.NpmPkg, 93 MetadataType: "NpmPackageLockJsonMetadata", 94 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, 95 }, 96 { 97 Name: "strip-ansi", 98 Version: "4.0.0", 99 PURL: "pkg:npm/strip-ansi@4.0.0", 100 Language: pkg.JavaScript, 101 Type: pkg.NpmPkg, 102 MetadataType: "NpmPackageLockJsonMetadata", 103 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, 104 }, 105 { 106 Name: "strip-eof", 107 Version: "1.0.0", 108 PURL: "pkg:npm/strip-eof@1.0.0", 109 Language: pkg.JavaScript, 110 Type: pkg.NpmPkg, 111 MetadataType: "NpmPackageLockJsonMetadata", 112 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, 113 }, 114 { 115 Name: "wordwrap", 116 Version: "0.0.3", 117 PURL: "pkg:npm/wordwrap@0.0.3", 118 Language: pkg.JavaScript, 119 Type: pkg.NpmPkg, 120 MetadataType: "NpmPackageLockJsonMetadata", 121 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, 122 }, 123 } 124 fixture := "test-fixtures/pkg-lock/package-lock.json" 125 for i := range expectedPkgs { 126 expectedPkgs[i].Locations.Add(file.NewLocation(fixture)) 127 } 128 129 pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships) 130 } 131 132 func TestParsePackageLockV2(t *testing.T) { 133 fixture := "test-fixtures/pkg-lock/lock-2/package-lock.json" 134 locationSet := file.NewLocationSet(file.NewLocation(fixture)) 135 npm := pkg.Package{ 136 Name: "npm", 137 Version: "6.14.6", 138 Language: pkg.JavaScript, 139 Type: pkg.NpmPkg, 140 PURL: "pkg:npm/npm@6.14.6", 141 MetadataType: "NpmPackageLockJsonMetadata", 142 Locations: locationSet, 143 Metadata: pkg.NpmPackageLockJSONMetadata{}, 144 } 145 propTypes := pkg.Package{ 146 Name: "@types/prop-types", 147 Version: "15.7.5", 148 PURL: "pkg:npm/%40types/prop-types@15.7.5", 149 Language: pkg.JavaScript, 150 Type: pkg.NpmPkg, 151 Licenses: pkg.NewLicenseSet( 152 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 153 ), 154 Locations: locationSet, 155 MetadataType: "NpmPackageLockJsonMetadata", 156 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha1-XxnSuFqY6VWANvajysyIGUIPBc8="}, 157 } 158 react := pkg.Package{ 159 Name: "@types/react", 160 Version: "18.0.17", 161 PURL: "pkg:npm/%40types/react@18.0.17", 162 Language: pkg.JavaScript, 163 Type: pkg.NpmPkg, 164 Licenses: pkg.NewLicenseSet( 165 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 166 ), 167 Locations: locationSet, 168 MetadataType: "NpmPackageLockJsonMetadata", 169 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", Integrity: "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ="}, 170 } 171 scheduler := pkg.Package{ 172 Name: "@types/scheduler", 173 Version: "0.16.2", 174 PURL: "pkg:npm/%40types/scheduler@0.16.2", 175 Language: pkg.JavaScript, 176 Type: pkg.NpmPkg, 177 Licenses: pkg.NewLicenseSet( 178 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 179 ), 180 Locations: locationSet, 181 MetadataType: "NpmPackageLockJsonMetadata", 182 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk="}, 183 } 184 csstype := pkg.Package{ 185 Name: "csstype", 186 Version: "3.1.0", 187 PURL: "pkg:npm/csstype@3.1.0", 188 Language: pkg.JavaScript, 189 Type: pkg.NpmPkg, 190 Licenses: pkg.NewLicenseSet( 191 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 192 ), 193 Locations: locationSet, 194 MetadataType: "NpmPackageLockJsonMetadata", 195 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", Integrity: "sha1-TdysNxjXh8+d8NG30VAzklyPKfI="}, 196 } 197 198 expectedPkgs := []pkg.Package{ 199 npm, 200 propTypes, 201 react, 202 scheduler, 203 csstype, 204 } 205 expectedRelationships := []artifact.Relationship{ 206 { 207 From: propTypes, 208 To: react, 209 Type: artifact.DependencyOfRelationship, 210 Data: nil, 211 }, 212 { 213 From: propTypes, 214 To: npm, 215 Type: artifact.DependencyOfRelationship, 216 Data: nil, 217 }, 218 { 219 From: react, 220 To: npm, 221 Type: artifact.DependencyOfRelationship, 222 Data: nil, 223 }, 224 { 225 From: scheduler, 226 To: react, 227 Type: artifact.DependencyOfRelationship, 228 Data: nil, 229 }, 230 { 231 From: scheduler, 232 To: npm, 233 Type: artifact.DependencyOfRelationship, 234 Data: nil, 235 }, 236 { 237 From: csstype, 238 To: react, 239 Type: artifact.DependencyOfRelationship, 240 Data: nil, 241 }, 242 { 243 From: csstype, 244 To: npm, 245 Type: artifact.DependencyOfRelationship, 246 Data: nil, 247 }, 248 } 249 250 for i := range expectedPkgs { 251 expectedPkgs[i].Locations.Add(file.NewLocation(fixture)) 252 } 253 pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships) 254 } 255 256 func TestParsePackageLockV3(t *testing.T) { 257 fixture := "test-fixtures/pkg-lock/lock-3/package-lock.json" 258 locationSet := file.NewLocationSet(file.NewLocation(fixture)) 259 lockV3Fixture := pkg.Package{ 260 Name: "lock-v3-fixture", 261 Version: "1.0.0", 262 Language: pkg.JavaScript, 263 Type: pkg.NpmPkg, 264 PURL: "pkg:npm/lock-v3-fixture@1.0.0", 265 MetadataType: "NpmPackageLockJsonMetadata", 266 Locations: locationSet, 267 Metadata: pkg.NpmPackageLockJSONMetadata{}, 268 } 269 propTypes := pkg.Package{ 270 Name: "@types/prop-types", 271 Version: "15.7.5", 272 Language: pkg.JavaScript, 273 Type: pkg.NpmPkg, 274 PURL: "pkg:npm/%40types/prop-types@15.7.5", 275 MetadataType: "NpmPackageLockJsonMetadata", 276 Locations: locationSet, 277 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="}, 278 } 279 react := pkg.Package{ 280 Name: "@types/react", 281 Version: "18.0.20", 282 Language: pkg.JavaScript, 283 Type: pkg.NpmPkg, 284 PURL: "pkg:npm/%40types/react@18.0.20", 285 MetadataType: "NpmPackageLockJsonMetadata", 286 Locations: locationSet, 287 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="}, 288 } 289 scheduler := pkg.Package{ 290 Name: "@types/scheduler", 291 Version: "0.16.2", 292 Language: pkg.JavaScript, 293 Type: pkg.NpmPkg, 294 PURL: "pkg:npm/%40types/scheduler@0.16.2", 295 MetadataType: "NpmPackageLockJsonMetadata", 296 Locations: locationSet, 297 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="}, 298 } 299 csstype := pkg.Package{ 300 Name: "csstype", 301 Version: "3.1.1", 302 Language: pkg.JavaScript, 303 Type: pkg.NpmPkg, 304 PURL: "pkg:npm/csstype@3.1.1", 305 MetadataType: "NpmPackageLockJsonMetadata", 306 Locations: locationSet, 307 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="}, 308 } 309 310 expectedPkgs := []pkg.Package{ 311 lockV3Fixture, 312 propTypes, 313 react, 314 scheduler, 315 csstype, 316 } 317 318 expectedRelationships := []artifact.Relationship{ 319 { 320 From: propTypes, 321 To: react, 322 Type: artifact.DependencyOfRelationship, 323 Data: nil, 324 }, 325 { 326 From: propTypes, 327 To: lockV3Fixture, 328 Type: artifact.DependencyOfRelationship, 329 Data: nil, 330 }, 331 { 332 From: react, 333 To: lockV3Fixture, 334 Type: artifact.DependencyOfRelationship, 335 Data: nil, 336 }, 337 { 338 From: scheduler, 339 To: react, 340 Type: artifact.DependencyOfRelationship, 341 Data: nil, 342 }, 343 { 344 From: scheduler, 345 To: lockV3Fixture, 346 Type: artifact.DependencyOfRelationship, 347 Data: nil, 348 }, 349 { 350 From: csstype, 351 To: react, 352 Type: artifact.DependencyOfRelationship, 353 Data: nil, 354 }, 355 { 356 From: csstype, 357 To: lockV3Fixture, 358 Type: artifact.DependencyOfRelationship, 359 Data: nil, 360 }, 361 } 362 363 for i := range expectedPkgs { 364 expectedPkgs[i].Locations.Add(file.NewLocation(fixture)) 365 } 366 pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships) 367 } 368 369 func TestParsePackageLockAlias(t *testing.T) { 370 var expectedRelationships []artifact.Relationship 371 commonPkgs := []pkg.Package{ 372 { 373 Name: "alias-check", 374 Version: "1.0.0", 375 PURL: "pkg:npm/alias-check@1.0.0", 376 Language: pkg.JavaScript, 377 Type: pkg.NpmPkg, 378 MetadataType: "NpmPackageLockJsonMetadata", 379 Metadata: pkg.NpmPackageLockJSONMetadata{}, 380 }, 381 { 382 Name: "case", 383 Version: "1.6.2", 384 PURL: "pkg:npm/case@1.6.2", 385 Language: pkg.JavaScript, 386 Type: pkg.NpmPkg, 387 MetadataType: "NpmPackageLockJsonMetadata", 388 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="}, 389 }, 390 { 391 Name: "case", 392 Version: "1.6.3", 393 PURL: "pkg:npm/case@1.6.3", 394 Language: pkg.JavaScript, 395 Type: pkg.NpmPkg, 396 MetadataType: "NpmPackageLockJsonMetadata", 397 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="}, 398 }, 399 { 400 Name: "@bundled-es-modules/chai", 401 Version: "4.2.2", 402 PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2", 403 Language: pkg.JavaScript, 404 Type: pkg.NpmPkg, 405 MetadataType: "NpmPackageLockJsonMetadata", 406 Metadata: pkg.NpmPackageLockJSONMetadata{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="}, 407 }, 408 } 409 410 packageLockV1 := "test-fixtures/pkg-lock/alias-1/package-lock.json" 411 packageLockV2 := "test-fixtures/pkg-lock/alias-2/package-lock.json" 412 packageLocks := []string{packageLockV1} 413 414 v2Pkg := pkg.Package{ 415 Name: "alias-check", 416 Version: "1.0.0", 417 PURL: "pkg:npm/alias-check@1.0.0", 418 Language: pkg.JavaScript, 419 Type: pkg.NpmPkg, 420 Licenses: pkg.NewLicenseSet( 421 pkg.NewLicenseFromLocations("ISC", file.NewLocation(packageLockV2)), 422 ), 423 MetadataType: "NpmPackageLockJsonMetadata", 424 Metadata: pkg.NpmPackageLockJSONMetadata{}, 425 } 426 427 for _, pl := range packageLocks { 428 expected := make([]pkg.Package, len(commonPkgs)) 429 copy(expected, commonPkgs) 430 431 if pl == packageLockV2 { 432 expected = append(expected, v2Pkg) 433 } 434 435 for i := range expected { 436 expected[i].Locations.Add(file.NewLocation(pl)) 437 } 438 pkgtest.TestFileParser(t, pl, parsePackageLock, expected, expectedRelationships) 439 } 440 } 441 442 func TestParsePackageLockLicenseWithArray(t *testing.T) { 443 fixture := "test-fixtures/pkg-lock/array-license/package-lock.json" 444 locationSet := file.NewLocationSet(file.NewLocation(fixture)) 445 pauseStream := pkg.Package{ 446 Name: "pause-stream", 447 Version: "0.0.11", 448 Language: pkg.JavaScript, 449 Type: pkg.NpmPkg, 450 Licenses: pkg.NewLicenseSet( 451 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 452 pkg.NewLicenseFromLocations("Apache2", file.NewLocation(fixture)), 453 ), 454 Locations: locationSet, 455 PURL: "pkg:npm/pause-stream@0.0.11", 456 MetadataType: "NpmPackageLockJsonMetadata", 457 Metadata: pkg.NpmPackageLockJSONMetadata{}, 458 } 459 through := pkg.Package{ 460 Name: "through", 461 Version: "2.3.8", 462 Language: pkg.JavaScript, 463 Type: pkg.NpmPkg, 464 Licenses: pkg.NewLicenseSet( 465 pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), 466 ), 467 Locations: locationSet, 468 PURL: "pkg:npm/through@2.3.8", 469 MetadataType: "NpmPackageLockJsonMetadata", 470 Metadata: pkg.NpmPackageLockJSONMetadata{}, 471 } 472 tmp := pkg.Package{ 473 Name: "tmp", 474 Version: "1.0.0", 475 Language: pkg.JavaScript, 476 Type: pkg.NpmPkg, 477 Licenses: pkg.NewLicenseSet( 478 pkg.NewLicenseFromLocations("ISC", file.NewLocation(fixture)), 479 ), 480 Locations: locationSet, 481 PURL: "pkg:npm/tmp@1.0.0", 482 MetadataType: "NpmPackageLockJsonMetadata", 483 Metadata: pkg.NpmPackageLockJSONMetadata{}, 484 } 485 486 expectedPkgs := []pkg.Package{ 487 pauseStream, 488 through, 489 tmp, 490 } 491 expectedRelationships := []artifact.Relationship{ 492 { 493 From: pauseStream, 494 To: tmp, 495 Type: artifact.DependencyOfRelationship, 496 Data: nil, 497 }, 498 { 499 From: through, 500 To: pauseStream, 501 Type: artifact.DependencyOfRelationship, 502 Data: nil, 503 }, 504 { 505 From: through, 506 To: tmp, 507 Type: artifact.DependencyOfRelationship, 508 Data: nil, 509 }, 510 } 511 for i := range expectedPkgs { 512 expectedPkgs[i].Locations.Add(file.NewLocation(fixture)) 513 } 514 pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships) 515 }