Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: There was an AttributeError deserializing JSON to <class 'cyclonedx.model.bom.Bom'> the Property #597

Closed
rms-sth opened this issue Apr 24, 2024 · 4 comments
Labels
duplicate This issue or pull request already exists

Comments

@rms-sth
Copy link

rms-sth commented Apr 24, 2024

Cannot parse the cyclonedx 1.5 SBOM:

My code:

import json
from typing import TYPE_CHECKING

from cyclonedx.exception import MissingOptionalDependencyException
from cyclonedx.model.bom import Bom
from cyclonedx.schema import SchemaVersion
from cyclonedx.validation.json import JsonStrictValidator

my_json_validator = JsonStrictValidator(SchemaVersion.V1_6)

try:
    file_path = "./test_cylonedx_sbom.json"
    with open(file_path) as f:
        deserialized_bom = Bom.from_json(data=json.loads(f.read()))
except MissingOptionalDependencyException as error:
    print("JSON-validation was skipped due to", error)

Error:

/home/user/fake/path/to/python /home/user/fake/path/to/calculator.py

Traceback (most recent call last):
  File "/home/user/fake/path/to/site-packages/serializable/__init__.py", line 324, in from_json
    items.append(prop_info.concrete_type.from_json(data=j))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/fake/path/to/site-packages/serializable/__init__.py", line 283, in from_json
    for k, v in data.items():
    ^^^^^^^^^^
AttributeError: 'str' object has no attribute 'items'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/user/fake/path/to/site-packages/serializable/__init__.py", line 333, in from_json
    _data[k] = prop_info.concrete_type.from_json(data=v)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/fake/path/to/site-packages/serializable/__init__.py", line 343, in from_json
    raise AttributeError(
AttributeError: There was an AttributeError deserializing JSON to <class 'cyclonedx.model.bom.BomMetaData'> the Property <s.oml.SerializableProperty name=tools, custom_names={}, array=True, enum=False, optional=False, c_type=<class 'cyclonedx.model.Tool'>, type=typing.Set[cyclonedx.model.Tool], custom_type=None, xml_attr=False, xml_sequence=3>: 'str' object has no attribute 'items'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/user/fake/path/to/calculator.py", line 49, in <module>
    deserialized_bom = Bom.from_json(data=json.loads(f.read()))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/fake/path/to/site-packages/serializable/__init__.py", line 343, in from_json
    raise AttributeError(
AttributeError: There was an AttributeError deserializing JSON to <class 'cyclonedx.model.bom.Bom'> the Property <s.oml.SerializableProperty name=metadata, custom_names={}, array=False, enum=False, optional=False, c_type=<class 'cyclonedx.model.bom.BomMetaData'>, type=<class 'cyclonedx.model.bom.BomMetaData'>, custom_type=None, xml_attr=False, xml_sequence=10>: There was an AttributeError deserializing JSON to <class 'cyclonedx.model.bom.BomMetaData'> the Property <s.oml.SerializableProperty name=tools, custom_names={}, array=True, enum=False, optional=False, c_type=<class 'cyclonedx.model.Tool'>, type=typing.Set[cyclonedx.model.Tool], custom_type=None, xml_attr=False, xml_sequence=3>: 'str' object has no attribute 'items'

CycloneDX SBOM:

{
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:af28ec13-79fa-424d-824e-de926edc5ae8",
  "version": 1,
  "metadata": {
    "timestamp": "2024-04-24T13:07:15+05:45",
    "tools": {
      "components": [
        {
          "type": "application",
          "author": "anchore",
          "name": "syft",
          "version": "1.2.0"
        }
      ]
    },
    "component": {
      "bom-ref": "f2447593a456a2a7",
      "type": "file",
      "name": "test3/"
    }
  },
  "components": [
    {
      "bom-ref": "pkg:pypi/black@24.2.0?package-id=d78dba8b757ae22c",
      "type": "library",
      "name": "black",
      "version": "24.2.0",
      "cpe": "cpe:2.3:a:python-black:python-black:24.2.0:*:*:*:*:*:*:*",
      "purl": "pkg:pypi/black@24.2.0",
      "properties": [
        { "name": "syft:package:foundBy", "value": "python-package-cataloger" },
        { "name": "syft:package:language", "value": "python" },
        { "name": "syft:package:type", "value": "python" },
        {
          "name": "syft:package:metadataType",
          "value": "python-pip-requirements-entry"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-black:python_black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_black:python-black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_black:python_black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python-black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python_black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:black:python-black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:black:python_black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-black:black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_black:black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:black:24.2.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:black:black:24.2.0:*:*:*:*:*:*:*"
        },
        { "name": "syft:location:0:path", "value": "/dev/requirements.txt" }
      ]
    },
    {
      "bom-ref": "pkg:pypi/flask@2.0.3?package-id=7aeb2a6c081f1782",
      "type": "library",
      "name": "flask",
      "version": "2.0.3",
      "cpe": "cpe:2.3:a:python-flask:python-flask:2.0.3:*:*:*:*:*:*:*",
      "purl": "pkg:pypi/flask@2.0.3",
      "properties": [
        { "name": "syft:package:foundBy", "value": "python-package-cataloger" },
        { "name": "syft:package:language", "value": "python" },
        { "name": "syft:package:type", "value": "python" },
        {
          "name": "syft:package:metadataType",
          "value": "python-pip-requirements-entry"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        { "name": "syft:location:0:path", "value": "/dev/requirements.txt" }
      ]
    },
    {
      "bom-ref": "pkg:pypi/flask@2.0.3?package-id=4947d30b71b34501",
      "type": "library",
      "name": "flask",
      "version": "2.0.3",
      "cpe": "cpe:2.3:a:python-flask:python-flask:2.0.3:*:*:*:*:*:*:*",
      "purl": "pkg:pypi/flask@2.0.3",
      "properties": [
        { "name": "syft:package:foundBy", "value": "python-package-cataloger" },
        { "name": "syft:package:language", "value": "python" },
        { "name": "syft:package:type", "value": "python" },
        {
          "name": "syft:package:metadataType",
          "value": "python-pip-requirements-entry"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:python-flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:python_flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python-flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python_flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:python:flask:2.0.3:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:flask:flask:2.0.3:*:*:*:*:*:*:*"
        },
        { "name": "syft:location:0:path", "value": "/requirements.txt" }
      ]
    }
  ]
}
@jkowalleck
Copy link
Member

quick tests: given JSON is valid to CDX1.5 and CDX 1.6

@jkowalleck
Copy link
Member

background: #561

@jkowalleck
Copy link
Member

@rms-sth Thank you for the report.

Be advised, that this library knows how to deserialize documents it created itself.
It might not yet capable of deserializing all CycloneDX features.

@jkowalleck
Copy link
Member

acknowledged.
this is due to the missing data models for that purpose. see #578


CycloneDX python library is maintained by volunteers, and drive by members of the Community.
Feel free to contribute the bits and peaces you or your organization needs.
If you plan on doing so, please let us know in a respective github issue or in our slack channel (invite)

@jkowalleck jkowalleck added the duplicate This issue or pull request already exists label Jun 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

2 participants