Giter Site home page Giter Site logo

lib4sbom's People

Contributors

anthonyharrison avatar eyu-dev avatar ffontaine avatar mastersans avatar nodet avatar rh0dy avatar rms-sth avatar sah-cdo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

lib4sbom's Issues

Own id is not saved. An id is always generated.

An id was set with the function set_id (SBOMPackage). However, a generated id is written when saving.

In my opinion, the problem can be found in the _validate_id function (File generator.py). len(re.findall(r"([0-9a-zA-Z.-+]+)$", id)) == len(id) is not correct here.

CPE for operating systems is not identified correctly

Hi Anthony,

I am generating a SBOM for neutrino RTOS. I noted that the CPE for older versions of that OS is:

cpe:2.3:o:blackberry:qnx_neutrino_rtos:6.5.0:sp1:*:*:*:*:*:*

The CPE generated by lib4sbom is:

cpe:/a:BlackBerry:qnx_neutrino_rtos:7.1

which converts to CPE 2.3:
cpe:2.3:a:BlackBerry:qnx_neutrino_rtos:7.1:*:*:*:*:*:*:*

Note the "a" (I assume for application) instead of "o" (for operating system?)

The outputted component correctly identifies as an operating system:
{ "type": "operating-system", "bom-ref": "blackberry:[email protected]", "name": "qnx_neutrino_rtos", "version": "7.1", "supplier": { "name": "BlackBerry" }, "cpe": "cpe:/a:BlackBerry:qnx_neutrino_rtos:7.1", "externalReferences": [ { "url": "https://blackberry.qnx.com/en/products/foundation-software/qnx-rtos", "type": "website", "comment": "Home page for project" } ] },

SBOM.set_version doesn't seem to work as expected

Hello,

Once again, thank you for this most excellent tool. I attempted to generate an SBOM in CycloneDX 1.4 format. I set the version to "1.4" and then generated the file, but it did not seem to set the specVersion or the BOM version correctly:

    my_sbom = SBOM()
    my_sbom.set_type(sbom_type='cyclonedx')
    my_sbom.set_version("1.4")

Output:

C:\Users\rhaley\tuleap\PythonSBOMTool\venv\Scripts\python.exe C:/Users/rhaley/tuleap/PythonSBOMTool/main.py 
Hi, PyCharm
{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuidbfda0bdf-f573-46c0-9f34-2fadfa634a1c",
  "version": 1,
  "metadata": {
  ...

We can see that the "schema" value was pointed to 1.4 but the "specVersion" is still 1.5 and the "version" was not affected at all.

As version is an overloaded term, I would think that to change the specification version would be a function call like set_specVersion() and set_version would affect the serial number version. That in my mind would be more consistent with the other "set_version" functions.

Thank you for considering this ticket.

Complete script here:

   print_hi('PyCharm')

    sbg = SBOMGenerator(format='json', sbom_type='cyclonedx')

    my_sbom = SBOM()
    my_sbom.set_type(sbom_type='cyclonedx')
    my_sbom.set_version("1.4")

    sbom_packages = {}
    my_package = SBOMPackage()
    my_package.set_name("glibc")
    my_package.set_version("2.15")
    my_package.set_supplier("organisation", "gnu")
    my_package.set_licensedeclared("GPL3")
    sbom_packages[(my_package.get_name(), my_package.get_value('version'))] = my_package.get_package()

    my_sbom.add_packages(sbom_packages)

    my_file = SBOMFile()
    my_file.set_name("OneTwoThree")
    my_file.set_licenseconcluded("MIT")
    hl = hashlib.sha256()
    hl.update(b"This really should point to a file...")
    filehash_hex = hl.hexdigest()
    my_file.set_checksum("SHA256", filehash_hex)
    files = {}
    files[my_file.get_name()] = my_file.get_file()
    my_sbom.add_files(files)

    # Will be displayed on console
    sbg.generate("ClinicianApp", my_sbom.get_sbom())

Broken CPE ID when supplier contains a digit

Same issue than #14, iperf3_project:iperf3 will be wrongly be translated into iperf_project:iperf3 resulting in a wrong CPE ID (and wrong purl). Code can easily be updated to add 0-9 in the regex but again it would probably be better to just remove the whole code?

Same package name in different manifest files does not appear after parsing the SPDX / CycloneDx file

Lets say I have two manifest files

  • requirements.txt : It contains flask==2.0.3
  • dev/requirements.txt : It contains flask==2.0.3

The generated SBOM packages looks like this:

[
  {
    "name": "flask",
    "SPDXID": "SPDXRef-Package-python-flask-7aeb2a6c081f1782",
    "versionInfo": "2.0.3",
    "supplier": "NOASSERTION",
    "downloadLocation": "NOASSERTION",
    "filesAnalyzed": false,
    "sourceInfo": "acquired package info from installed python package manifest file: /dev/requirements.txt",
    "licenseConcluded": "NOASSERTION",
    "licenseDeclared": "NOASSERTION",
    "copyrightText": "NOASSERTION",
    "externalRefs": [
      {
        "referenceCategory": "SECURITY",
        "referenceType": "cpe23Type",
        "referenceLocator": "cpe:2.3:a:python-flask:python-flask:2.0.3:*:*:*:*:*:*:*"
      }
    ]
  },
  {
    "name": "flask",
    "SPDXID": "SPDXRef-Package-python-flask-4947d30b71b34501",
    "versionInfo": "2.0.3",
    "supplier": "NOASSERTION",
    "downloadLocation": "NOASSERTION",
    "filesAnalyzed": false,
    "sourceInfo": "acquired package info from installed python package manifest file: /requirements.txt",
    "licenseConcluded": "NOASSERTION",
    "licenseDeclared": "NOASSERTION",
    "copyrightText": "NOASSERTION",
    "externalRefs": [
      {
        "referenceCategory": "SECURITY",
        "referenceType": "cpe23Type",
        "referenceLocator": "cpe:2.3:a:python-flask:python-flask:2.0.3:*:*:*:*:*:*:*"
      }
    ]
  }
]

But after parsing with lib4sbom only one of the package is returned by get_packages()

Desire output: Both packages should be returned after parsing.

Broken CPE ID when supplier contains -

The following line will result in a broken CPE ID when a supplier contain a - such as d-bus_project or json-c_project:

names = re.findall(r"[a-zA-Z\.\]+ [A-Za-z]+", supplier_name)

For example, above line will split d-bus_project as d, bus and project and concatenate it into d bus project.
Then, the piece of code below will replace to _ resulting in the wrong d_bus_project vendor instead of the correct d-bus_project:

f'<cpe>cpe:/a:{package["supplier"].replace(" ", "_")}:{name}:{version}</cpe>'

I don't understand what is the goal of this piece of code so I don't know how to "fix" it properly.

TypeError: 'SBOMDocument' object is not iterable

Hello Anthony. I am using lib4sbom 0.5.1 to generate SBOM output. I am trying to add an SBOMDocument to my SBOM and I am running into the above error. Here is the code that I added to my SBOM:

` sbom_document = SBOMDocument()

sbom_document.set_name("ClinicianApp")

sbom_document.set_metadata_version("1.2.2-46")

sbom.add_document(sbom_document)`

And it generates the following error now:

File "C:\Users\rhaley\AppData\Local\JetBrains\Toolbox\apps\PyCharm-P\ch-0\222.3345.131\plugins\python\helpers\pydev\pydevd.py", line 1496, in _exec pydev_imports.execfile(file, globals, locals) # execute the script ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\rhaley\AppData\Local\JetBrains\Toolbox\apps\PyCharm-P\ch-0\222.3345.131\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile exec(compile(contents+"\n", file, 'exec'), glob, loc) File "C:/Users/rhaley/tuleap/SBOMTools/Client1/Client1_clinician_app.py", line 114, in <module> generate_clinician_sbom() File "C:/Users/rhaley/tuleap/SBOMTools/Client1/Client1_clinician_app.py", line 109, in generate_clinician_sbom sbg.generate("iOSApp", sbom.get_sbom()) File "C:\Users\rhaley\AppData\Local\Programs\Python\Python311\Lib\site-packages\lib4sbom\generator.py", line 81, in generate self._generate_cyclonedx(project_name, sbom_data) File "C:\Users\rhaley\AppData\Local\Programs\Python\Python311\Lib\site-packages\lib4sbom\generator.py", line 287, in _generate_cyclonedx doc.copy_document(sbom_data["document"]) File "C:\Users\rhaley\AppData\Local\Programs\Python\Python311\Lib\site-packages\lib4sbom\data\document.py", line 79, in copy_document for key in document: TypeError: 'SBOMDocument' object is not iterable python-BaseException

I tried modifying the copy_document function and this change works:

def copy_document(self, document):

        for key in document.document:

            self.set_value(key, document.document[key])

Error on parsing CyclonDX

Hello again.
Other error it's:

>>> from lib4sbom.parser import SBOMParser
>>> test = SBOMParser()
>>> test.parse_file("test_data/cyclondx/node-alma.json")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dm/Job/R-Vision/tools/cronjobs/src/trivy/plugin/venv/lib/python3.11/site-packages/lib4sbom/parser.py", line 80, in parse_file
    ) = self.parser.parse(filename)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dm/Job/R-Vision/tools/cronjobs/src/trivy/plugin/venv/lib/python3.11/site-packages/lib4sbom/cyclonedx/cyclonedx_parser.py", line 18, in parse
    return self.parse_cyclonedx_json(sbom_file)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dm/Job/R-Vision/tools/cronjobs/src/trivy/plugin/venv/lib/python3.11/site-packages/lib4sbom/cyclonedx/cyclonedx_parser.py", line 143, in parse_cyclonedx_json
    target = id[target_id]
             ~~^^^^^^^^^^^
KeyError: 'pkg:npm/[email protected]?file_path=usr%2Flocal%2Flib%2Fnode_modules%2Fnpm%2Fnode_modules%2Fagent-base%2Fpackage.json'

file for parsing in attachment(it's should be json)

node-alma.txt

Issue when use test_parser.parse_file("file")

Hi, all the information are here :
File "/usr/lib/python3.11/site-packages/lib4sbom/cyclonedx/cyclonedx_parser.py", line 353, in _parse_component_xml self.cyclonedx_package.set_property(params["name"], params["value"])

image

SBOM.get_files sometimes returns a dictionary rather than a list

The SBOM.get_files() function is typed as returning a List:

def get_files(self) -> List:
file_data = self.sbom.get("files", [])
if len(file_data) > 0:
return [x for x in self.sbom["files"].values()]
return file_data

The SBOM.add_files() function takes a dictionary of files and stores the dictionary of files:

def add_files(self, files: Dict):
self.sbom["files"] = files

The three scenarios that can occur are:

  1. SBOM.get_files() is called when SBOM.add_files() has not been called
  2. SBOM.get_files() is called when SBOM.add_files() has been called with an empty dictionary (no files)
  3. SBOM.get_files() is called when SBOM.add_files() has been called with a dictionary containing 1 or more files

In case 1 the function returns a List because "files" is not in the dictionary, and so a default List is returned.
In case 3 the function returns a List because the list-comprehension generates a new list.
In case 2 the function returns a Dictionary because the dictionary is empty and so is returned unmodified.

This is resulting in a crash of in the https://github.com/anthonyharrison/sbommerge utility. Specifically if it's provided an SBOM with an empty file list, it gets a dictionary rather than a list, and its iteration throws due to getting an unexpected type.

'hasExtractedLicensingInfos' list is ignored

It looks like the 'hasExtractedLicensingInfos' part of JSON SBOM files (defined at https://spdx.github.io/spdx-spec/v2.3/other-licensing-information-detected/) is just ignored. I didn't find where it is processed in SPDXParser._parse_spdx_data, and I didn't find where it would be handled in SPDXGenerator. generateJSONDocumentHeader either.

Running the following in the root of the repo shows the issue. Some of the diff is expected, but not the missing license.

$ git log --oneline -1
5a29562 (HEAD -> main, origin/main, origin/HEAD) fix: generation of lifecycle

$ python -c 'from lib4sbom.parser import SBOMParser; from lib4sbom.generator import SBOMGenerator; parser=SBOMParser(); parser.parse_file("test.spdx.json"); gen = SBOMGenerator(False, sbom_type="spdx", format="json"); gen.generate("TestApp", parser.get_sbom())' > test-output.spdx.json; diff test.spdx.json test-output.spdx.json
7c7
<       "Tool: lib4sbom-0.5.3"
---
>       "Tool: lib4sbom-0.7.1"
9c9
<     "created": "2023-12-18T14:41:48Z",
---
>     "created": "2024-05-03T10:52:15Z",
14,21c14
<   "documentNamespace": "http://spdx.org/spdxdocs/iOSApp_Application-urn:uuid:My_uuid_1234",
<   "hasExtractedLicensingInfos": [
<     {
<       "licenseId": "LicenseRef-1",
<       "name": "SwiftTrace License",
<       "extractedText": "Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to [...] licensing details.\n"
<     }
<   ],
---
>   "documentNamespace": "http://spdx.org/spdxdocs/iOSApp_Application-11dc6b2b-2023-405b-8b7f-d62c3d3f7e0d",
69,73d61
<     },
<     {
<       "spdxElementId": "SPDXRef-Package-None",
<       "relatedSpdxElement": "SPDXRef-Package-1-iOSApp",
<       "relationshipType": "DESCRIBES"

NameError Exception When 'package_info' Contains 'description' Field

Hi,

the variable "fpackage_info" has not been declared in this context.

This can lead to a NameError exception like so:

  File "/root/.local/lib/python3.11/site-packages/lib4sbom/generator.py", line 78, in generate
    self._generate_spdx(project_name, sbom_data)
  File "/root/.local/lib/python3.11/site-packages/lib4sbom/generator.py", line 133, in _generate_spdx
    self.bom.generatePackageDetails(
  File "/root/.local/lib/python3.11/site-packages/lib4sbom/spdx/spdx_generator.py", line 443, in generatePackageDetails
    self.generateJSONPackageDetails(
  File "/root/.local/lib/python3.11/site-packages/lib4sbom/spdx/spdx_generator.py", line 335, in generateJSONPackageDetails
    component["description"] = fpackage_info["description"]
                               ^^^^^^^^^^^^^
NameError: name 'fpackage_info' is not defined. Did you mean: 'package_info'?

Cheers!

local variable 'version' referenced before assignment

I have this trace if i parse Cyclondx Json file

Traceback (most recent call last):
  File "/opt/project/src/test.py", line 15, in <module>
    test_parser.parse_file("sbom.json")
  File "/usr/local/lib/python3.10/site-packages/lib4sbom/parser.py", line 81, in parse_file
    ) = self.parser.parse(filename)
  File "/usr/local/lib/python3.10/site-packages/lib4sbom/cyclonedx/cyclonedx_parser.py", line 19, in parse
    return self.parse_cyclonedx_json(sbom_file)
  File "/usr/local/lib/python3.10/site-packages/lib4sbom/cyclonedx/cyclonedx_parser.py", line 143, in parse_cyclonedx_json
    packages[(package, version)] = cyclonedx_package.get_package()
UnboundLocalError: local variable 'version' referenced before assignment

incorrect generate_output functionality

Hello.
Thank you for package.
I found some error for function SBOMOutput() generate_output

from lib4sbom.parser import SBOMParser
from lib4sbom.generator import SBOMOutput


base_parse = SBOMParser()
base_parse.parse_file('test_data/almalinux.spdx')


sbom_output = SBOMOutput(output_format='Tag')
sbom_output.generate_output(base_parse.get_sbom())

the output is only keys of dataset:

type
files
packages
relationships
document

Is it expected behavior?

My case it's parse sbom, delete some packages and relationships and then get new sbom on this date.
generate() functions is not for me, becouse it changes some metadata like tools for example.

sbom file attached.

Improved parser file handling

Lib4SBOM follows the conventions for file names for SPDX documents and determines the type of SBOM based on the extension e.g. a file with extension .spdx is assumed to be tag Value, .spdx.json is a file in SJON format. However if a filename does not conform to the naming convention, the file will be attempted to be parsed by the CycloneDX parser.

However filenames with extensions such as .sbom, .txt etc are unlikely to be parsed correctly and generate an exception. This needs to be improved so that invalid filename extensions are handled approriately.

The CycloneDX parser just needs to recognize the CycloneDX filename conventions of .bom.json, .cdx.json. .bom.xml and .cdx.xml

Functionality Questions for CycloneDX SBOM

Hello Anthony!

I've been very pleased to work with your library for the last few weeks. I have a number of questions that relates to our particular use case producing CycloneDX SBOMs. I have listed all the questions here, but would be happy to open separate tickets if you like. Also, if these turn out to be new features or bugs that you want to include but don't have time to implement, please let me know and I will look at implementing them myself. I have included the python file that helped me generate these questions.

  • Lib4SBOM is not outputing LicenseDeclared but does output LicenseConcluded? (see swiftlog_pkg)
  • CycloneDX allows for multiple licenses
  • Is there any way to specify the license text and/or a custom URL?
  • ID not outputted (See: any subcomponent)?
  • Would like to manually set BOM-Ref (would like bom-ref to be the same as ID)?
  • External reference not outputted (see: gbdeviceinfo_pkg)?
  • How to set metadata.component.type - Would like to set this to firmware?
  • How to set metadata.component.supplier?
  • How to set metadata.component.version?
  • Will "relationships" be exposed as cyclonedx dependencies? Was unable to get relationships to work? (I'm a Lua guy, so I am not familiar with all of Pythons intricacies so it might be my fault.). (see: relationships at the bottom of the file)
    -- I see output for an array of dependencies in the output but I don't know how to fill it?
  • No class for vulnerabilities?
  • I would still like to be able to set the UUID and the version of the SBOM. (e.g. one UUID and change version number when the software updates)

Thanks so much!
Russ

from lib4sbom.data.file import SBOMFile
from lib4sbom.data.package import SBOMPackage
from lib4sbom.generator import SBOMGenerator
from lib4sbom.sbom import SBOMData, SBOM
from lib4sbom.data.relationship import SBOMRelationship

import hashlib


def generate_clinician_sbom():
    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")

    sbom_packages = {}

    # Atlantis
    atlantis_pkg = SBOMPackage()
    atlantis_pkg.set_name("Atlantis")
    atlantis_pkg.set_version("1.22.0")
    atlantis_pkg.set_supplier("Author", "Proxyman")
    atlantis_pkg.set_homepage("https://proxyman.io/")
    atlantis_pkg.set_licensedeclared("Apache-2.0")
    atlantis_pkg.set_id(atlantis_pkg.get_name().lower() + "proxyman.io@" + atlantis_pkg.get_value('version'))
    sbom_packages[(atlantis_pkg.get_name(), atlantis_pkg.get_value('version'))] = \
        atlantis_pkg.get_package()

    # Cocoa Lumberjack
    cocoalumberjack_pkg = SBOMPackage()
    cocoalumberjack_pkg.set_name("CocoaLumberjack")
    cocoalumberjack_pkg.set_version("3.8.1")
    cocoalumberjack_pkg.set_supplier("Author", "CocoaLumberjack")
    cocoalumberjack_pkg.set_homepage("https://github.com/CocoaLumberjack")
    cocoalumberjack_pkg.set_licensedeclared("BSD-3-Clause")
    cocoalumberjack_pkg.set_id(cocoalumberjack_pkg.get_name().lower() + "@" + cocoalumberjack_pkg.get_value('version'))
    sbom_packages[(cocoalumberjack_pkg.get_name(), cocoalumberjack_pkg.get_value('version'))] = \
        cocoalumberjack_pkg.get_package()

    # GBDeviceInfo
    gbdeviceinfo_pkg = SBOMPackage()
    gbdeviceinfo_pkg.set_name("GBDeviceInfo")
    gbdeviceinfo_pkg.set_version("7.2.0")
    gbdeviceinfo_pkg.set_supplier("Author", "Luka Mirosevic")
    gbdeviceinfo_pkg.set_homepage("https://github.com/lmirosevic/GBDeviceInfo")
    gbdeviceinfo_pkg.set_licensedeclared("Apache-2.0")
    gbdeviceinfo_pkg.set_id(gbdeviceinfo_pkg.get_name().lower() + "@" + gbdeviceinfo_pkg.get_value('version'))
    gbdeviceinfo_pkg.set_externalreference("vcs", "vcs", "https://github.com/lmirosevic/GBDeviceInfo")
    sbom_packages[(gbdeviceinfo_pkg.get_name(), gbdeviceinfo_pkg.get_value('version'))] = \
        gbdeviceinfo_pkg.get_package()



    # swift-log
    swiftlog_pkg = SBOMPackage()
    swiftlog_pkg.set_name("swift-log")
    swiftlog_pkg.set_version("1.5.2")
    swiftlog_pkg.set_supplier("Author", "Apple Inc.")
    swiftlog_pkg.set_homepage("https://github.com/apple/swift-log")
    # swiftlog_pkg.set_licensedeclared("Apache-2.0")
    swiftlog_pkg.set_licenseconcluded("Apache-2.0")
    swiftlog_pkg.set_id(swiftlog_pkg.get_name().lower() + ".apple.com@" + swiftlog_pkg.get_value('version'))
    sbom_packages[(swiftlog_pkg.get_name(), swiftlog_pkg.get_value('version'))] = \
        swiftlog_pkg.get_package()

    # SwiftTrace
    swifttrace_pkg = SBOMPackage()
    swifttrace_pkg.set_name("SwiftTrace")
    swifttrace_pkg.set_version("8.4.6")
    swifttrace_pkg.set_supplier("Author", "John Holdsworth")
    swifttrace_pkg.set_homepage("https://github.com/johnno1962/SwiftTrace")
    swifttrace_pkg.set_licensedeclared("Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
                                       "of this software and associated documentation files (the \"Software\"), to deal\n"
                                       "in the Software without restriction, including without limitation the rights\n"
                                       "to use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\n"
                                       "copies of the Software, and to permit persons to whom the Software is\n"
                                       "furnished to do so, subject to the following conditions:\n\n"
                                       "The above copyright notice and this permission notice shall be included in\n"
                                       "all copies or substantial portions of the Software.\n\n"
                                       "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
                                       "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
                                       "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
                                       "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
                                       "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
                                       "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"
                                       "THE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\n"
                                       "following github project which is licensed under the terms of that project:\n\n"
                                       "https:\/\/github.com\/OliverLetterer\/imp_implementationForwardingToSelector\n\n"
                                       "Now uses the very handy https:\/\/github.com\/facebook\/fishhook.\n"
                                       "See the source and header files for licensing details.\n")
    swifttrace_pkg.set_id(swifttrace_pkg.get_name().lower() + "@" + swifttrace_pkg.get_value('version'))
    sbom_packages[(swifttrace_pkg.get_name(), swifttrace_pkg.get_value('version'))] = \
        swifttrace_pkg.get_package()

    sbom.add_packages(sbom_packages)
    # relationships = {}
    # rel1 = SBOMRelationship()
    # rel1.set_relationship("CDXRef-DOCUMENT", "CONTAINS", "1-Atlantis")
    # # relationships.append(rel1)
    # # relationships.update(rel1)
    # relationships[(rel1.get_source(), rel1.get_target())] = rel1.get_relationship()
    # sbom.add_relationships(relationships)
    sbg = SBOMGenerator(format='json', sbom_type='cyclonedx')

    sbg.generate("iOSApp", sbom.get_sbom())
    # sbg.generate("iOSApp", sbom.get_sbom(), "mybomy-bom.json")

Output:

{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:62ae0766-846d-4c9d-89f7-c484712e81ba",
  "version": 1,
  "metadata": {
    "timestamp": "2023-08-25T11:55:22Z",
    "tools": [
      {
        "name": "lib4sbom",
        "version": "0.4.2"
      }
    ],
    "component": {
      "type": "application",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "iOSApp"
    }
  },
  "components": [
    {
      "type": "library",
      "bom-ref": "1-Atlantis",
      "name": "Atlantis",
      "version": "1.22.0",
      "supplier": {
        "name": "Proxyman"
      },
      "cpe": "cpe:/a:Proxyman:Atlantis:1.22.0",
      "externalReferences": [
        {
          "url": "https://proxyman.io/",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "2-CocoaLumberjack",
      "name": "CocoaLumberjack",
      "version": "3.8.1",
      "supplier": {
        "name": "CocoaLumberjack"
      },
      "cpe": "cpe:/a:CocoaLumberjack:CocoaLumberjack:3.8.1",
      "externalReferences": [
        {
          "url": "https://github.com/CocoaLumberjack",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "3-GBDeviceInfo",
      "name": "GBDeviceInfo",
      "version": "7.2.0",
      "supplier": {
        "name": "Luka Mirosevic"
      },
      "cpe": "cpe:/a:Luka_Mirosevic:GBDeviceInfo:7.2.0",
      "externalReferences": [
        {
          "url": "https://github.com/lmirosevic/GBDeviceInfo",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "4-swift-log",
      "name": "swift-log",
      "version": "1.5.2",
      "supplier": {
        "name": "Apple Inc."
      },
      "cpe": "cpe:/a:Apple_Inc.:swift-log:1.5.2",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/apple/swift-log",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "5-SwiftTrace",
      "name": "SwiftTrace",
      "version": "8.4.6",
      "supplier": {
        "name": "John Holdsworth"
      },
      "cpe": "cpe:/a:John_Holdsworth:SwiftTrace:8.4.6",
      "externalReferences": [
        {
          "url": "https://github.com/johnno1962/SwiftTrace",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    }
  ],
  "dependencies": []
}

Handle bom-ref as optional parameter

bom-ref is an optional parameter ina CycloneDX document. The CycloneDX parser doesn't currently recognise this.

Whilst most components should have a bom-ref, if the parser detects a component without one, it will automatically generate one.

SBOM serialNumber Is Missing A Colon

Hello,

Thank you for the fantastic library. This will greatly shorten my path to generating SBOMs. I have generated a test SBOM in CycloneDX format and the serial number appears to be missing a colon:

  "serialNumber": "urn:uuidbfda0bdf-f573-46c0-9f34-2fadfa634a1c",

Should be

  "serialNumber": "urn:uuid:bfda0bdf-f573-46c0-9f34-2fadfa634a1c",

Is there any way to set the serialNumber manually? I was hoping to use one serialNumber and increment the "version" identifier. However, you already have an SBOM.set_version function that seems to set the "specVersion" but not completely. I will open a separate issue for that.

Error parsing SPDX JSON file

NOASSERTION for Orignator in SPDX JSON file results in IndexError

  File "/usr/local/lib/python3.10/dist-packages/lib4sbom/spdx/spdx_parser.py", line 26, in parse
    return self.parse_spdx_json(sbom_file)
  File "/usr/local/lib/python3.10/dist-packages/lib4sbom/spdx/spdx_parser.py", line 278, in parse_spdx_json
    return self._parse_spdx_data(data)
  File "/usr/local/lib/python3.10/dist-packages/lib4sbom/spdx/spdx_parser.py", line 359, in _parse_spdx_data
    spdx_package.set_originator(originator[0], originator[1])
IndexError: list index out of range

CycloneDX Assembly Support

More recent versions of CycloneDX support an assembly which is a nested set of components within other components. This doesn't imply relationship data, but makes it easier to manage SBOMs where there are multiple sources or services as each major component can be added as a set of child components of its parent.

Whilst I recognise lib4sbom isn't designed to be a fully featured CycloneDx parser, I believe support should be added for at least parsing assemblies. I recognise this will likely need to flatten them and some fidelity will be lost with the current internal model, however, this would be beneficial for those of us using assemblies for validation and basic parsing tasks.

feat: Include provided locations in cyclonedx sbom report utilizing evidence key.

The cycloneDX report needs to be enriched with the file location where the products are found. This should follow the cycloneDX format which utilizes Evidence field with Occurrences to show locations.

Screenshot 2024-03-06 210620

The locations of products would be provided in
https://github.com/intel/cve-bin-tool/blob/3f15be82b8cd87108642b2c2a9fa800b88e479be/cve_bin_tool/output_engine/__init__.py#L906

and the lib4sbom is expected to handle this and include locations in report
Screenshot 2024-03-20 223441

Conversion of cdx json sbom to spdx json sbom file misses download location and license information

The license information and download location of the conversion from cdx.json to spdx.json misses the value.

`from lib4sbom.parser import SBOMParser
from lib4sbom.generator import SBOMGenerator
from lib4sbom.data.document import SBOMDocument

test_parser = SBOMParser()
test_parser.parse_file("gl-sbom-conan-conan.cdx.json")`

One example package in gl-sbom-conan-conan.cdx.json:
{
"name": "openssl",
"version": "3.1.3",
"purl": "pkg:conan/[email protected]",
"type": "library",
"bom-ref": "pkg:conan/[email protected]",
"licenses": [
{
"license": {
"id": "Apache-2.0"
}
}
],
"URL": "https://gitlab.com/test/libraries/open-source-libraries/-/tree/main/packages/openssl",
"description": "A toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols",
"copyrightText": "",
"downloadLocation": "['https://www.openssl.org/source/openssl-3.1.3.tar.gz', 'https://github.com/openssl/openssl/releases/download/openssl-3.1.3/openssl-3.1.3.tar.gz']",
"hashes": [
{
"alg": "SHA-256",
"content": "f0316a2ebd89e7f2352976445458689f804755958788c466692fb2a188b2eacf6"
}
],
"patch_file": "[{'patch_file': 'patches/3.1.1-fix-qcc-compilation.patch', 'base_path': ''}]"
},

When converted to gl-sbom-conan-conan.spdx.json, the downloadLocation and licenseConcluded got NOASSERTION instead of the actual value.
{
"SPDXID": "SPDXRef-Package-46-openssl",
"name": "openssl",
"versionInfo": "3.1.3",
"primaryPackagePurpose": "LIBRARY",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"checksums": [
{
"algorithm": "SHA256",
"checkumValue": "f0316a2ebd89e7f2352976445458689f804755958788c466692fb2a188b2eacf6"
}
],
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"description": "A toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:conan/[email protected]"
}
]
},

Metadata component bom-ref with cyclonedx is not linked to an actual component

When creating a cyclonedx sbom via sbom4python and therefore this library, the metadata -> component -> bom-ref property is set to CDXRef-DOCUMENT and this value is not present in any of the bom-ref properties of the non-metadata components elsewhere in the sbom.

For example with the sbom for the radon module created by [email protected] and [email protected]:

"metadata": {
    ...
    "component": {
      "type": "application",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "Python-radon"
    }
}
    ...
"components": [
{
  "type": "application",
  "bom-ref": "1-radon",
   ...

(This was created with pip 23.3 and Python 3.11)

It seems this issue is the result of a somewhat recent change, as in an sbom created by [email protected] the CDXRef-DOCUMENT property value is present in the proper component as well.

However, I would advocate for the metadata bom-ref and the related component to both contain something like 1-radon rather than CDXRef-DOCUMENT.

Packages with same name Ignored in the scan of SPDX file

For reference do checkout this.
Related: cve-bin-tool issue 4058

while scanning a spdx sbom file in json format containing two different version packages of openssl the tools is outputing only 1 package whereas is should display both, only first occurence of the package is displayed, on investigation it is found that it is due to this particular if statement:

if package not in packages:

below is a output of a print statement showing contents of packages dictionary where is can be seen only one package is taken into account:

{
    "openssl": {
        "name": "openssl",
        "type": "LIBRARY",
        "version": "1.1.1f",
        "id": "openssl_1.1.1f",
        "supplier_type": "Organization",
        "supplier": "OpenSSL",
        "originator_type": "Organization",
        "originator": "OpenSSL",
        "homepage": "http://www.openssl.org/",
        "licenseconcluded": "LicenseRef-OpenSSL",
        "licensedeclared": "LicenseRef-OpenSSL",
        "downloadlocation": "http://www.openssl.org/source/",
        "description": "OpenSSL library version 1.1.1f",
    }
}

Version manipulation

As per semantic versioning standards , pre release versions can contain hyphens but in lib4sbom we are changing the version by splitting the hyphens . Do we have any logical reason behind this like only major versions to be detected @anthonyharrison ?

Manipulation code

def _semantic_version(self, version):
return version.split("-")[0] if "-" in version else version

Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.