diff --git a/src/cyclone_dx_sbom.js b/src/cyclone_dx_sbom.js index e47bdf65..9efce1c5 100644 --- a/src/cyclone_dx_sbom.js +++ b/src/cyclone_dx_sbom.js @@ -58,30 +58,31 @@ export default class CycloneDxSbom { rootComponent components dependencies + constructor() { this.dependencies = new Array() this.components = new Array() } + /** * @param {PackageURL} root - add main/root component for sbom * @return {CycloneDxSbom} the CycloneDxSbom Sbom Object */ - addRoot (root) { + addRoot(root) { this.rootComponent = - getComponent(root,"application") + getComponent(root, "application") this.components.push(this.rootComponent) return this } - /** * @return {{{"bom-ref": string, name, purl: string, type, version}}} root component of sbom. */ - getRoot (){ + getRoot() { return this.rootComponent } @@ -90,52 +91,52 @@ export default class CycloneDxSbom { * @param {PackageURL} targetRef current dependency to add to Dependencies list of component sourceRef * @return Sbom */ - addDependency(sourceRef, targetRef){ + addDependency(sourceRef, targetRef) { let componentIndex = this.getComponentIndex(sourceRef); - if(componentIndex < 0) - { - this.components.push(getComponent(sourceRef,"library")) + if (componentIndex < 0) { + this.components.push(getComponent(sourceRef, "library")) } let dependencyIndex = this.getDependencyIndex(sourceRef.purl) - if(dependencyIndex < 0) - { + if (dependencyIndex < 0) { this.dependencies.push(createDependency(sourceRef.purl)) dependencyIndex = this.getDependencyIndex(sourceRef.purl) } //Only if the dependency doesn't exists on the dependency list of dependency, then add it to this list. - if(this.dependencies[dependencyIndex].dependsOn.findIndex(dep => dep === targetRef.toString()) === -1) - { + if (this.dependencies[dependencyIndex].dependsOn.findIndex(dep => dep === targetRef.toString()) === -1) { this.dependencies[dependencyIndex].dependsOn.push(targetRef.toString()) } - if(this.getDependencyIndex(targetRef.toString()) < 0) - { + if (this.getDependencyIndex(targetRef.toString()) < 0) { this.dependencies.push(createDependency(targetRef.toString())) } - let newComponent = getComponent(targetRef,"library"); + let newComponent = getComponent(targetRef, "library"); // Only if component doesn't exists in component list, add it to the list. - if(this.getComponentIndex(newComponent) < 0) - { + if (this.getComponentIndex(newComponent) < 0) { this.components.push(newComponent) } return this } + /** * @return String CycloneDx Sbom json object in a string format */ - getAsJsonString(){ + getAsJsonString() { this.sbomObject = { - "bomFormat" : "CycloneDX", - "specVersion" : "1.4", - "version" : 1, - "metadata" : { - "timestamp" : new Date(), - "component" : this.rootComponent + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "metadata": { + "timestamp": new Date(), + "component": this.rootComponent }, - "components" : this.components, - "dependencies" : this.dependencies + "components": this.components, + "dependencies": this.dependencies + } + if (this.rootComponent === undefined) + { + delete this.sbomObject.metadata.component } - if(process.env["EXHORT_DEBUG"] === "true") { + if (process.env["EXHORT_DEBUG"] === "true") { console.log("SBOM Generated for manifest, to be sent to exhort service:" + EOL + JSON.stringify(this.sbomObject, null, 4)) } return JSON.stringify(this.sbomObject) @@ -146,7 +147,7 @@ export default class CycloneDxSbom { * @param {String} dependency - purl string of the component. * @return {int} - the index of the dependency in dependencies Array, returns -1 if not found. */ - getDependencyIndex(dependency){ + getDependencyIndex(dependency) { return this.dependencies.findIndex(dep => dep.ref === dependency) } @@ -156,7 +157,7 @@ export default class CycloneDxSbom { * @return {int} index of the found component entry, if not found returns -1. * @private */ - getComponentIndex(theComponent){ + getComponentIndex(theComponent) { return this.components.findIndex(component => component.purl === theComponent.purl) } @@ -165,33 +166,30 @@ export default class CycloneDxSbom { * @param purl {PackageURL} * @return component */ - purlToComponent(purl) - { - return getComponent(purl,"library") + purlToComponent(purl) { + return getComponent(purl, "library") } + /** * This method gets an array of dependencies to be ignored, and remove all of them from CycloneDx Sbom * @param {Array} dependencies to be removed from sbom * @return {CycloneDxSbom} without ignored dependencies */ - filterIgnoredDeps(deps){ + filterIgnoredDeps(deps) { deps.forEach(dep => { - let index = this.components.findIndex(component => component.name === dep ); - if(index>=0) - { - this.components.splice(index,1) + let index = this.components.findIndex(component => component.name === dep); + if (index >= 0) { + this.components.splice(index, 1) } index = this.dependencies.findIndex(dependency => dependency.ref.includes(dep)); - if(index>=0) - { - this.dependencies.splice(index,1) + if (index >= 0) { + this.dependencies.splice(index, 1) } this.dependencies.forEach(dependency => { let indexDependsOn = dependency.dependsOn.findIndex(theDep => theDep.includes(dep)); - if (indexDependsOn > -1 ) - { - dependency.dependsOn.splice(indexDependsOn,1) + if (indexDependsOn > -1) { + dependency.dependsOn.splice(indexDependsOn, 1) } }) }) @@ -203,24 +201,21 @@ export default class CycloneDxSbom { * @param {Array} dependencies to be removed from sbom * @return {CycloneDxSbom} without ignored dependencies */ - filterIgnoredDepsIncludingVersion(deps){ + filterIgnoredDepsIncludingVersion(deps) { deps.forEach(dep => { - let index = this.components.findIndex(component => component.purl === dep ); - if(index>=0) - { - this.components.splice(index,1) + let index = this.components.findIndex(component => component.purl === dep); + if (index >= 0) { + this.components.splice(index, 1) } index = this.dependencies.findIndex(dependency => dependency.ref === dep); - if(index>=0) - { - this.dependencies.splice(index,1) + if (index >= 0) { + this.dependencies.splice(index, 1) } this.dependencies.forEach(dependency => { - let indexDependsOn = dependency.dependsOn.findIndex(theDep => theDep === dep ); - if (indexDependsOn > -1 ) - { - dependency.dependsOn.splice(indexDependsOn,1) + let indexDependsOn = dependency.dependsOn.findIndex(theDep => theDep === dep); + if (indexDependsOn > -1) { + dependency.dependsOn.splice(indexDependsOn, 1) } }) }) @@ -233,24 +228,28 @@ export default class CycloneDxSbom { * * @return {boolean} */ - checkIfPackageInsideDependsOnList(component, name) - { + checkIfPackageInsideDependsOnList(component, name) { let dependencyIndex = this.getDependencyIndex(component.purl) - if(dependencyIndex < 0) - { + if (dependencyIndex < 0) { return false } //Only if the dependency doesn't exists on the dependency list of dependency, then add it to this list. - if(this.dependencies[dependencyIndex].dependsOn.findIndex(dep => dep.includes(name) ) >= 0) - { + if (this.dependencies[dependencyIndex].dependsOn.findIndex(dep => dep.includes(name)) >= 0) { return true; - } - else { + } else { return false } } - + /** Removes the root component from the sbom + */ + removeRootComponent() { + let compIndex = this.getComponentIndex(this.rootComponent) + let depIndex = this.getDependencyIndex(this.rootComponent.purl) + this.components.splice(compIndex, 1) + this.dependencies.splice(depIndex, 1) + this.rootComponent = undefined + } } diff --git a/src/providers/python_pip.js b/src/providers/python_pip.js index ebd7eae5..e46c2952 100644 --- a/src/providers/python_pip.js +++ b/src/providers/python_pip.js @@ -179,6 +179,8 @@ function createSbomStackAnalysis(manifest, opts = {}) { }) let requirementTxtContent = fs.readFileSync(manifest).toString(); handleIgnoredDependencies(requirementTxtContent,sbom) + // In python there is no root component, then we must remove the dummy root we added, so the sbom json will be accepted by exhort backend + sbom.removeRootComponent() return sbom.getAsJsonString() @@ -208,6 +210,8 @@ function getSbomForComponentAnalysis(data, opts = {}) { }) fs.rmSync(tmpDir, { recursive: true, force: true }); handleIgnoredDependencies(data,sbom) + // In python there is no root component, then we must remove the dummy root we added, so the sbom json will be accepted by exhort backend + sbom.removeRootComponent() return sbom.getAsJsonString() } diff --git a/src/sbom.js b/src/sbom.js index c3248ba3..4f0df0b5 100644 --- a/src/sbom.js +++ b/src/sbom.js @@ -73,6 +73,13 @@ export default class Sbom { { return this.sbomModel.checkIfPackageInsideDependsOnList(component,name) } + + /** Removes the root component from the sbom + */ + removeRootComponent() + { + return this.sbomModel.removeRootComponent() + } } diff --git a/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_component_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_component_sbom.json index a6ea38ac..a010ff2b 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_component_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_component_sbom.json @@ -3,21 +3,9 @@ "specVersion" : "1.4", "version" : 1, "metadata" : { - "timestamp" : "2023-10-01T00:00:00.000Z", - "component" : { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - } + "timestamp" : "2023-10-01T00:00:00.000Z" }, "components" : [ - { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - }, { "name" : "anyio", "version" : "3.6.2", @@ -195,36 +183,6 @@ } ], "dependencies" : [ - { - "ref" : "pkg:pypi/root", - "dependsOn" : [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref" : "pkg:pypi/anyio@3.6.2", "dependsOn" : [ ] diff --git a/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_stack_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_stack_sbom.json index 46d43c3b..a674719b 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_stack_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_txt_ignore/expected_stack_sbom.json @@ -3,21 +3,9 @@ "specVersion": "1.4", "version": 1, "metadata": { - "timestamp": "2023-10-01T00:00:00.000Z", - "component": { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - } + "timestamp": "2023-10-01T00:00:00.000Z" }, "components": [ - { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - }, { "name": "anyio", "version": "3.6.2", @@ -195,36 +183,6 @@ } ], "dependencies": [ - { - "ref": "pkg:pypi/root", - "dependsOn": [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref": "pkg:pypi/anyio@3.6.2", "dependsOn": [ diff --git a/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_component_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_component_sbom.json index d25c54c5..7bb60340 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_component_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_component_sbom.json @@ -3,21 +3,9 @@ "specVersion" : "1.4", "version" : 1, "metadata" : { - "timestamp" : "2023-10-01T00:00:00.000Z", - "component" : { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - } + "timestamp" : "2023-10-01T00:00:00.000Z" }, "components" : [ - { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - }, { "name" : "anyio", "version" : "3.6.2", @@ -209,38 +197,6 @@ } ], "dependencies" : [ - { - "ref" : "pkg:pypi/root", - "dependsOn" : [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/click@8.0.4", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/pydantic@1.9.2", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref" : "pkg:pypi/anyio@3.6.2", "dependsOn" : [ ] diff --git a/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_stack_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_stack_sbom.json index 305e1d2c..9d5bc9da 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_stack_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_txt_no_ignore/expected_stack_sbom.json @@ -3,21 +3,9 @@ "specVersion": "1.4", "version": 1, "metadata": { - "timestamp": "2023-10-01T00:00:00.000Z", - "component": { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - } + "timestamp": "2023-10-01T00:00:00.000Z" }, "components": [ - { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - }, { "name": "anyio", "version": "3.6.2", @@ -209,38 +197,6 @@ } ], "dependencies": [ - { - "ref": "pkg:pypi/root", - "dependsOn": [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/click@8.0.4", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/pydantic@1.9.2", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref": "pkg:pypi/anyio@3.6.2", "dependsOn": [ diff --git a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_component_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_component_sbom.json index d25c54c5..7675fcfe 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_component_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_component_sbom.json @@ -4,20 +4,8 @@ "version" : 1, "metadata" : { "timestamp" : "2023-10-01T00:00:00.000Z", - "component" : { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - } }, "components" : [ - { - "name" : "root", - "purl" : "pkg:pypi/root", - "type" : "application", - "bom-ref" : "pkg:pypi/root" - }, { "name" : "anyio", "version" : "3.6.2", @@ -209,38 +197,6 @@ } ], "dependencies" : [ - { - "ref" : "pkg:pypi/root", - "dependsOn" : [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/click@8.0.4", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/pydantic@1.9.2", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref" : "pkg:pypi/anyio@3.6.2", "dependsOn" : [ ] diff --git a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_stack_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_stack_sbom.json index 305e1d2c..9d5bc9da 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_stack_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_txt_no_ignore/expected_stack_sbom.json @@ -3,21 +3,9 @@ "specVersion": "1.4", "version": 1, "metadata": { - "timestamp": "2023-10-01T00:00:00.000Z", - "component": { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - } + "timestamp": "2023-10-01T00:00:00.000Z" }, "components": [ - { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - }, { "name": "anyio", "version": "3.6.2", @@ -209,38 +197,6 @@ } ], "dependencies": [ - { - "ref": "pkg:pypi/root", - "dependsOn": [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/click@8.0.4", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/pydantic@1.9.2", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref": "pkg:pypi/anyio@3.6.2", "dependsOn": [ diff --git a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_with_ignore/expected_stack_sbom.json b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_with_ignore/expected_stack_sbom.json index 46d43c3b..a674719b 100644 --- a/test/providers/tst_manifests/pip/pip_requirements_virtual_env_with_ignore/expected_stack_sbom.json +++ b/test/providers/tst_manifests/pip/pip_requirements_virtual_env_with_ignore/expected_stack_sbom.json @@ -3,21 +3,9 @@ "specVersion": "1.4", "version": 1, "metadata": { - "timestamp": "2023-10-01T00:00:00.000Z", - "component": { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - } + "timestamp": "2023-10-01T00:00:00.000Z" }, "components": [ - { - "name": "root", - "purl": "pkg:pypi/root", - "type": "application", - "bom-ref": "pkg:pypi/root" - }, { "name": "anyio", "version": "3.6.2", @@ -195,36 +183,6 @@ } ], "dependencies": [ - { - "ref": "pkg:pypi/root", - "dependsOn": [ - "pkg:pypi/anyio@3.6.2", - "pkg:pypi/asgiref@3.4.1", - "pkg:pypi/beautifulsoup4@4.12.2", - "pkg:pypi/certifi@2023.7.22", - "pkg:pypi/chardet@4.0.0", - "pkg:pypi/contextlib2@21.6.0", - "pkg:pypi/fastapi@0.75.1", - "pkg:pypi/flask@2.0.3", - "pkg:pypi/h11@0.13.0", - "pkg:pypi/idna@2.10", - "pkg:pypi/immutables@0.19", - "pkg:pypi/importlib-metadata@4.8.3", - "pkg:pypi/itsdangerous@2.0.1", - "pkg:pypi/jinja2@3.0.3", - "pkg:pypi/markupsafe@2.0.1", - "pkg:pypi/requests@2.25.1", - "pkg:pypi/six@1.16.0", - "pkg:pypi/sniffio@1.2.0", - "pkg:pypi/soupsieve@2.3.2.post1", - "pkg:pypi/starlette@0.17.1", - "pkg:pypi/typing-extensions@4.1.1", - "pkg:pypi/urllib3@1.26.16", - "pkg:pypi/uvicorn@0.17.0", - "pkg:pypi/werkzeug@2.0.3", - "pkg:pypi/zipp@3.6.0" - ] - }, { "ref": "pkg:pypi/anyio@3.6.2", "dependsOn": [