CycloneDX / cyclonedx-python

CycloneDX Software Bill of Materials (SBOM) generator for Python projects and environments
https://cyclonedx.org
Apache License 2.0
243 stars 64 forks source link

Release v0.4.0 breaks when pypi returns a null license #103

Closed rback123 closed 3 years ago

rback123 commented 4 years ago

Release v0.4.0 breaks when pypi returns a null license. Sometimes packages will have empty strings for a license and sometimes they will have null.

Actual Results

(cyclonedx_venv) -bash-4.2$ cyclonedx-py -i output/xad -o output/RICK_bom.xml
Input file: output/xad
Output BOM: output/RICK_bom.xml
JSON output: False
Package info url: https://pypi.org/pypi/{package_name}/{package_version}/json
Generating CycloneDX BOM
Traceback (most recent call last):
  File "/var/lib/jenkins/venvs/cyclonedx_venv/bin/cyclonedx-py", line 8, in <module>
    sys.exit(main())
  File "/var/lib/jenkins/venvs/cyclonedx_venv/lib/python3.6/site-packages/cyclonedx/client.py", line 83, in main
    bom_contents = generate_bom(args)
  File "/var/lib/jenkins/venvs/cyclonedx_venv/lib/python3.6/site-packages/cyclonedx/client.py", line 59, in generate_bom
    bom_contents = reader.read_bom(fd, args.package_info_url, args.json)
  File "/var/lib/jenkins/venvs/cyclonedx_venv/lib/python3.6/site-packages/cyclonedx/bom/reader.py", line 23, in read_bom
    for component in all_components:
  File "/var/lib/jenkins/venvs/cyclonedx_venv/lib/python3.6/site-packages/cyclonedx/bom/reader.py", line 18, in <genexpr>
    all_components = (get_component(req, package_info_url) for req in requirements.parse(fd))
  File "/var/lib/jenkins/venvs/cyclonedx_venv/lib/python3.6/site-packages/cyclonedx/bom/reader.py", line 67, in get_component
    if package_license != 'UNKNOWN' and len(package_license.strip()) > 0:
AttributeError: 'NoneType' object has no attribute 'strip'

Expected Results

I expect the SBOM to be generated successfully.

Examples

I found a couple packages that demonstrate the issue.

Alabaster 0.7.9 and 0.7.10

Sample requirements.txt

alabaster==0.7.9

pypi response

Note: Building the SBOM fails when the license is null but is successful when the license is an empty string.

$ curl -s https://pypi.org/pypi/alabaster/0.7.9/json | python -m json.tool | grep license
        "license": null,
$ curl -s https://pypi.org/pypi/alabaster/0.7.10/json | python -m json.tool | grep license
        "license": null,
$ curl -s https://pypi.org/pypi/alabaster/0.7.11/json | python -m json.tool | grep license
        "license": "",
$ curl -s https://pypi.org/pypi/alabaster/0.7.12/json | python -m json.tool | grep license
        "license": "",

pbr 1.10.0

Sample requirements.txt

pbr==1.10.0

pypi response

Note: Building the SBOM fails when the license is null but is successful when the license is an empty string.

$ curl -s https://pypi.org/pypi/pbr/1.10.0/json | python -m json.tool | grep license
        "license": null,
$ curl -s https://pypi.org/pypi/pbr/2.0.0/json | python -m json.tool | grep license
        "license": "",
coderpatros commented 4 years ago

Fixed in version 0.4.1, but I'll leave this issue open as a reminder to add a test for this.