diff --git a/pkg/npm/npm.go b/pkg/npm/npm.go index 24a40cfd18..a130b69770 100644 --- a/pkg/npm/npm.go +++ b/pkg/npm/npm.go @@ -356,8 +356,9 @@ func (exec *Execute) checkIfLockFilesExist() (bool, bool, error) { // CreateBOM generates BOM file using CycloneDX from all package.json files func (exec *Execute) CreateBOM(packageJSONFiles []string) error { execRunner := exec.Utils.GetExecRunner() - // Install CycloneDX Node.js module locally without saving in package.json - err := execRunner.RunExecutable("npm", "install", cycloneDxPackageVersion, "--no-save") + // Install CycloneDX Node.js module via npx without saving in package.json / polluting globals + // See https://github.com/CycloneDX/cyclonedx-node-npm#installation + err := execRunner.RunExecutable("npx", "--package", cycloneDxPackageVersion, "--call", "exit") if err != nil { return fmt.Errorf("failed to install cycloneDx package: %w", err) } @@ -366,6 +367,7 @@ func (exec *Execute) CreateBOM(packageJSONFiles []string) error { for _, packageJSONFile := range packageJSONFiles { path := filepath.Dir(packageJSONFile) params := []string{ + cycloneDxPackageVersion, "--output-format", "XML", "--spec-version", @@ -373,7 +375,7 @@ func (exec *Execute) CreateBOM(packageJSONFiles []string) error { "--output-file", filepath.Join(path, npmBomFilename), packageJSONFile, } - err := execRunner.RunExecutable("cyclonedx-npm", params...) + err := execRunner.RunExecutable("npx", params...) if err != nil { return fmt.Errorf("failed to generate cycloneDx BOM: %w", err) } diff --git a/pkg/npm/npm_test.go b/pkg/npm/npm_test.go index 93480a7376..f1b42a0f81 100644 --- a/pkg/npm/npm_test.go +++ b/pkg/npm/npm_test.go @@ -360,13 +360,13 @@ func TestNpm(t *testing.T) { if assert.NoError(t, err) { if assert.Equal(t, 3, len(utils.execRunner.Calls)) { - assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"install", "--global", "@cyclonedx/cyclonedx-npm@1.11.0", "--no-save"}}, utils.execRunner.Calls[0]) - assert.Equal(t, mock.ExecCall{Exec: "cyclonedx-npm", Params: []string{"--output-format", + assert.Equal(t, mock.ExecCall{Exec: "npx", Params: []string{"--package", "@cyclonedx/cyclonedx-npm@1.11.0", "--call", "exit"}}, utils.execRunner.Calls[0]) + assert.Equal(t, mock.ExecCall{Exec: "npx", Params: []string{"@cyclonedx/cyclonedx-npm@1.11.0", "--output-format", "XML", "--spec-version", "1.4", "--output-file", "bom-npm.xml", "package.json"}}, utils.execRunner.Calls[1]) - assert.Equal(t, mock.ExecCall{Exec: "cyclonedx-npm", Params: []string{"--output-format", + assert.Equal(t, mock.ExecCall{Exec: "npx", Params: []string{"@cyclonedx/cyclonedx-npm@1.11.0", "--output-format", "XML", "--spec-version", "1.4",