diff --git a/src/providers/golang_gomodules.js b/src/providers/golang_gomodules.js index e0fddf5..e67bd0f 100644 --- a/src/providers/golang_gomodules.js +++ b/src/providers/golang_gomodules.js @@ -258,17 +258,22 @@ function getSBOM(manifest, opts = {}, includeTransitive) { } let manifestDir = path.dirname(manifest) try { - var goGraphOutput = invokeCommand(goBin, ['mod', 'graph'], {cwd: manifestDir}).toString() + var goGraphOutput = invokeCommand(goBin, ['mod', 'graph'], {cwd: manifestDir}).toString().trim() } catch(error) { throw new Error('failed to invoke go binary for module graph', {cause: error}) } + + try { + var goModEditOutput = JSON.parse(invokeCommand(goBin, ["mod", "edit", "-json"], {cwd: manifestDir}).toString().trim()) + } catch(error) { + throw new Error('failed to determine root module name', {cause: error}) + } + let ignoredDeps = getIgnoredDeps(manifest); let allIgnoredDeps = ignoredDeps.map((dep) => dep.toString()) let sbom = new Sbom(); - let rows = goGraphOutput.split(getLineSeparatorGolang()).filter(line => { - return !line.includes(' go@'); - }); - let root = getParentVertexFromEdge(rows[0]) + let rows = goGraphOutput.split(getLineSeparatorGolang()).filter(line => !line.includes(' go@')); + let root = getParentVertexFromEdge(goModEditOutput['Module']['Path']) let matchManifestVersions = getCustom("MATCH_MANIFEST_VERSIONS", "false", opts); if(matchManifestVersions === "true") { performManifestVersionsCheck(root, rows, manifest) @@ -278,7 +283,7 @@ function getSBOM(manifest, opts = {}, includeTransitive) { sbom.addRoot(mainModule) const exhortGoMvsLogicEnabled = getCustom("EXHORT_GO_MVS_LOGIC_ENABLED", "false", opts) if(includeTransitive && exhortGoMvsLogicEnabled === "true") { - rows = getFinalPackagesVersionsForModule(rows,manifest,goBin) + rows = getFinalPackagesVersionsForModule(rows, manifest, goBin) } if (includeTransitive) { let currentParent = "" diff --git a/test/providers/golang_gomodules.test.js b/test/providers/golang_gomodules.test.js index f1b5894..32063f9 100644 --- a/test/providers/golang_gomodules.test.js +++ b/test/providers/golang_gomodules.test.js @@ -23,7 +23,8 @@ suite('testing the golang-go-modules data provider', () => { "go_mod_no_ignore", "go_mod_with_ignore", "go_mod_test_ignore", - "go_mod_with_all_ignore" + "go_mod_with_all_ignore", + "go_mod_empty" ].forEach(testCase => { let scenario = testCase.replace('go_mod_', '').replaceAll('_', ' ') test(`verify go.mod sbom provided for stack analysis with scenario ${scenario}`, () => { diff --git a/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_component_analysis.json b/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_component_analysis.json new file mode 100644 index 0000000..17455b3 --- /dev/null +++ b/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_component_analysis.json @@ -0,0 +1,27 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "metadata": { + "timestamp": "2023-08-07T00:00:00.000Z", + "component": { + "group": "github.com/sample", + "name": "empty-module", + "version": "v0.0.0", + "purl": "pkg:golang/github.com/sample/empty-module@v0.0.0", + "type": "application", + "bom-ref": "pkg:golang/github.com/sample/empty-module@v0.0.0" + } + }, + "components": [ + { + "group": "github.com/sample", + "name": "empty-module", + "version": "v0.0.0", + "purl": "pkg:golang/github.com/sample/empty-module@v0.0.0", + "type": "application", + "bom-ref": "pkg:golang/github.com/sample/empty-module@v0.0.0" + } + ], + "dependencies": [] +} diff --git a/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_stack_analysis.json b/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_stack_analysis.json new file mode 100644 index 0000000..a41eed4 --- /dev/null +++ b/test/providers/tst_manifests/golang/go_mod_empty/expected_sbom_stack_analysis.json @@ -0,0 +1,52 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "metadata": { + "timestamp": "2023-08-07T00:00:00.000Z", + "component": { + "group": "github.com/sample", + "name": "empty-module", + "version": "v0.0.0", + "purl": "pkg:golang/github.com/sample/empty-module@v0.0.0", + "type": "application", + "bom-ref": "pkg:golang/github.com/sample/empty-module@v0.0.0" + } + }, + "components": [ + { + "group": "github.com/sample", + "name": "empty-module", + "version": "v0.0.0", + "purl": "pkg:golang/github.com/sample/empty-module@v0.0.0", + "type": "application", + "bom-ref": "pkg:golang/github.com/sample/empty-module@v0.0.0" + }, + { + "name": "go", + "version": "1.24", + "purl": "pkg:golang/go@1.24", + "type": "library", + "bom-ref": "pkg:golang/go@1.24" + }, + { + "name": "toolchain", + "version": "go1.24", + "purl": "pkg:golang/toolchain@go1.24", + "type": "library", + "bom-ref": "pkg:golang/toolchain@go1.24" + } + ], + "dependencies": [ + { + "ref": "pkg:golang/go@1.24", + "dependsOn": [ + "pkg:golang/toolchain@go1.24" + ] + }, + { + "ref": "pkg:golang/toolchain@go1.24", + "dependsOn": [] + } + ] +} diff --git a/test/providers/tst_manifests/golang/go_mod_empty/go.mod b/test/providers/tst_manifests/golang/go_mod_empty/go.mod new file mode 100644 index 0000000..a2af790 --- /dev/null +++ b/test/providers/tst_manifests/golang/go_mod_empty/go.mod @@ -0,0 +1,3 @@ +module github.com/sample/empty-module + +go 1.24