Skip to content

Commit da14f74

Browse files
committed
feat: add basic support for CDX 1.5
Signed-off-by: Johannes Feichtner <[email protected]>
1 parent 3189e59 commit da14f74

File tree

63 files changed

+14294
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+14294
-21
lines changed

cyclonedx/model/__init__.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
NoPropertiesProvidedException,
3131
UnknownHashTypeException,
3232
)
33-
from ..schema.schema import SchemaVersion1Dot3, SchemaVersion1Dot4
33+
from ..schema.schema import SchemaVersion1Dot3, SchemaVersion1Dot4, SchemaVersion1Dot5
3434

3535
"""
3636
Uniform set of models to represent objects within a CycloneDX software bill-of-materials.
@@ -395,22 +395,45 @@ class ExternalReferenceType(str, Enum):
395395
See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.3/#type_externalReferenceType
396396
"""
397397

398+
ADVERSARY_MODEL = 'adversary-model' # Only supported in >= 1.5
398399
ADVISORIES = 'advisories'
400+
ATTESTATION = 'attestation' # Only supported in >= 1.5
399401
BOM = 'bom'
400402
BUILD_META = 'build-meta'
401403
BUILD_SYSTEM = 'build-system'
404+
CERTIFICATION_REPORT = 'certification-report' # Only supported in >= 1.5
402405
CHAT = 'chat'
406+
CODIFIED_INFRASTRUCTURE = 'codified-infrastructure' # Only supported in >= 1.5
407+
COMPONENT_ANALYSIS_REPORT = 'component-analysis-report' # Only supported in >= 1.5
408+
CONFIGURATION = 'configuration' # Only supported in >= 1.5
403409
DISTRIBUTION = 'distribution'
410+
DISTRIBUTION_INTAKE = 'distribution-intake' # Only supported in >= 1.5
404411
DOCUMENTATION = 'documentation'
412+
DYNAMIC_ANALYSIS_REPORT = 'dynamic-analysis-report' # Only supported in >= 1.5
413+
EVIDENCE = 'evidence' # Only supported in >= 1.5
414+
EXPLOITABILITY_STATEMENT = 'exploitability-statement' # Only supported in >= 1.5
415+
FORMULATION = 'formulation' # Only supported in >= 1.5
405416
ISSUE_TRACKER = 'issue-tracker'
406417
LICENSE = 'license'
418+
LOG = 'log' # Only supported in >= 1.5
407419
MAILING_LIST = 'mailing-list'
420+
MATURITY_REPORT = 'maturity-report' # Only supported in >= 1.5
421+
MODEL_CARD = 'model-card' # Only supported in >= 1.5
408422
OTHER = 'other'
423+
PENTEST_REPORT = 'pentest-report' # Only supported in >= 1.5
424+
POAM = 'poam' # Only supported in >= 1.5
425+
QUALITY_METRICS = 'quality-metrics' # Only supported in >= 1.5
409426
RELEASE_NOTES = 'release-notes' # Only supported in >= 1.4
427+
RISK_ASSESSMENT = 'risk-assessment' # Only supported in >= 1.5
428+
RUNTIME_ANALYSIS_REPORT = 'runtime-analysis-report' # Only supported in >= 1.5
429+
SECURITY_CONTACT = 'security-contact' # Only supported in >= 1.5
430+
STATIC_ANALYSIS_REPORT = 'static-analysis-report' # Only supported in >= 1.5
410431
SOCIAL = 'social'
411432
SCM = 'vcs'
412433
SUPPORT = 'support'
434+
THREAT_MODEL = 'threat-model' # Only supported in >= 1.5
413435
VCS = 'vcs'
436+
VULNERABILITY_ASSERTION = 'vulnerability-assertion' # Only supported in >= 1.5
414437
WEBSITE = 'website'
415438

416439

@@ -541,6 +564,7 @@ def type(self, type: ExternalReferenceType) -> None:
541564
@property
542565
@serializable.view(SchemaVersion1Dot3)
543566
@serializable.view(SchemaVersion1Dot4)
567+
@serializable.view(SchemaVersion1Dot5)
544568
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'hash')
545569
def hashes(self) -> 'SortedSet[HashType]':
546570
"""
@@ -1052,6 +1076,7 @@ def hashes(self, hashes: Iterable[HashType]) -> None:
10521076

10531077
@property
10541078
@serializable.view(SchemaVersion1Dot4)
1079+
@serializable.view(SchemaVersion1Dot5)
10551080
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
10561081
@serializable.xml_sequence(5)
10571082
def external_references(self) -> 'SortedSet[ExternalReference]':

cyclonedx/model/bom.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
SchemaVersion1Dot2,
3434
SchemaVersion1Dot3,
3535
SchemaVersion1Dot4,
36+
SchemaVersion1Dot5,
3637
)
3738
from ..serialization import LicenseRepositoryHelper, UrnUuidHelper
3839
from . import ExternalReference, OrganizationalContact, OrganizationalEntity, Property, ThisTool, Tool, get_now_utc
@@ -53,7 +54,7 @@ class BomMetaData:
5354
This is our internal representation of the metadata complex type within the CycloneDX standard.
5455
5556
.. note::
56-
See the CycloneDX Schema for Bom metadata: https://cyclonedx.org/docs/1.4/#type_metadata
57+
See the CycloneDX Schema for Bom metadata: https://cyclonedx.org/docs/1.5/#type_metadata
5758
"""
5859

5960
def __init__(self, *, tools: Optional[Iterable[Tool]] = None,
@@ -187,6 +188,7 @@ def supplier(self, supplier: Optional[OrganizationalEntity]) -> None:
187188
@property
188189
@serializable.view(SchemaVersion1Dot3)
189190
@serializable.view(SchemaVersion1Dot4)
191+
@serializable.view(SchemaVersion1Dot5)
190192
@serializable.type_mapping(LicenseRepositoryHelper)
191193
@serializable.xml_sequence(7)
192194
def licenses(self) -> LicenseRepository:
@@ -205,6 +207,7 @@ def licenses(self, licenses: Iterable[License]) -> None:
205207
@property
206208
@serializable.view(SchemaVersion1Dot3)
207209
@serializable.view(SchemaVersion1Dot4)
210+
@serializable.view(SchemaVersion1Dot5)
208211
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property')
209212
@serializable.xml_sequence(8)
210213
def properties(self) -> 'SortedSet[Property]':
@@ -294,6 +297,7 @@ def __init__(self, *, components: Optional[Iterable[Component]] = None,
294297
@serializable.view(SchemaVersion1Dot2)
295298
@serializable.view(SchemaVersion1Dot3)
296299
@serializable.view(SchemaVersion1Dot4)
300+
@serializable.view(SchemaVersion1Dot5)
297301
@serializable.xml_attribute()
298302
def serial_number(self) -> UUID:
299303
"""
@@ -313,6 +317,7 @@ def serial_number(self, serial_number: UUID) -> None:
313317
@serializable.view(SchemaVersion1Dot2)
314318
@serializable.view(SchemaVersion1Dot3)
315319
@serializable.view(SchemaVersion1Dot4)
320+
@serializable.view(SchemaVersion1Dot5)
316321
@serializable.xml_sequence(1)
317322
def metadata(self) -> BomMetaData:
318323
"""
@@ -392,6 +397,7 @@ def has_component(self, component: Component) -> bool:
392397
@serializable.view(SchemaVersion1Dot2)
393398
@serializable.view(SchemaVersion1Dot3)
394399
@serializable.view(SchemaVersion1Dot4)
400+
@serializable.view(SchemaVersion1Dot5)
395401
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'service')
396402
@serializable.xml_sequence(3)
397403
def services(self) -> 'SortedSet[Service]':
@@ -412,6 +418,7 @@ def services(self, services: Iterable[Service]) -> None:
412418
@serializable.view(SchemaVersion1Dot2)
413419
@serializable.view(SchemaVersion1Dot3)
414420
@serializable.view(SchemaVersion1Dot4)
421+
@serializable.view(SchemaVersion1Dot5)
415422
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
416423
@serializable.xml_sequence(4)
417424
def external_references(self) -> 'SortedSet[ExternalReference]':
@@ -462,6 +469,7 @@ def has_vulnerabilities(self) -> bool:
462469

463470
@property
464471
@serializable.view(SchemaVersion1Dot4)
472+
@serializable.view(SchemaVersion1Dot5)
465473
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'vulnerability')
466474
@serializable.xml_sequence(8)
467475
def vulnerabilities(self) -> 'SortedSet[Vulnerability]':
@@ -490,6 +498,7 @@ def version(self, version: int) -> None:
490498
@serializable.view(SchemaVersion1Dot2)
491499
@serializable.view(SchemaVersion1Dot3)
492500
@serializable.view(SchemaVersion1Dot4)
501+
@serializable.view(SchemaVersion1Dot5)
493502
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'dependency')
494503
@serializable.xml_sequence(5)
495504
def dependencies(self) -> 'SortedSet[Dependency]':

cyclonedx/model/component.py

+16
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
SchemaVersion1Dot2,
3333
SchemaVersion1Dot3,
3434
SchemaVersion1Dot4,
35+
SchemaVersion1Dot5,
3536
)
3637
from ..serialization import BomRefHelper, LicenseRepositoryHelper, PackageUrl
3738
from . import (
@@ -255,12 +256,16 @@ class ComponentType(str, Enum):
255256
"""
256257
APPLICATION = 'application'
257258
CONTAINER = 'container'
259+
DATA = 'data'
258260
DEVICE = 'device'
261+
DEVICE_DRIVER = 'device-driver'
259262
FILE = 'file'
260263
FIRMWARE = 'firmware'
261264
FRAMEWORK = 'framework'
262265
LIBRARY = 'library'
266+
MACHINE_LEARNING_MODEL = 'machine-learning-model'
263267
OPERATING_SYSTEM = 'operating-system'
268+
PLATFORM = 'platform'
264269

265270

266271
class Diff:
@@ -528,6 +533,7 @@ def commits(self, commits: Iterable[Commit]) -> None:
528533
@serializable.view(SchemaVersion1Dot2)
529534
@serializable.view(SchemaVersion1Dot3)
530535
@serializable.view(SchemaVersion1Dot4)
536+
@serializable.view(SchemaVersion1Dot5)
531537
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'patch')
532538
@serializable.xml_sequence(5)
533539
def patches(self) -> 'SortedSet[Patch]':
@@ -849,6 +855,7 @@ def mime_type(self, mime_type: Optional[str]) -> None:
849855
@serializable.view(SchemaVersion1Dot2)
850856
@serializable.view(SchemaVersion1Dot3)
851857
@serializable.view(SchemaVersion1Dot4)
858+
@serializable.view(SchemaVersion1Dot5)
852859
@serializable.xml_attribute()
853860
@serializable.xml_name('bom-ref')
854861
def bom_ref(self) -> BomRef:
@@ -867,6 +874,7 @@ def bom_ref(self) -> BomRef:
867874
@serializable.view(SchemaVersion1Dot2)
868875
@serializable.view(SchemaVersion1Dot3)
869876
@serializable.view(SchemaVersion1Dot4)
877+
@serializable.view(SchemaVersion1Dot5)
870878
@serializable.xml_sequence(1)
871879
def supplier(self) -> Optional[OrganizationalEntity]:
872880
"""
@@ -886,6 +894,7 @@ def supplier(self, supplier: Optional[OrganizationalEntity]) -> None:
886894
@serializable.view(SchemaVersion1Dot2)
887895
@serializable.view(SchemaVersion1Dot3)
888896
@serializable.view(SchemaVersion1Dot4)
897+
@serializable.view(SchemaVersion1Dot5)
889898
@serializable.xml_sequence(2)
890899
def author(self) -> Optional[str]:
891900
"""
@@ -1028,6 +1037,7 @@ def hashes(self, hashes: Iterable[HashType]) -> None:
10281037
@serializable.view(SchemaVersion1Dot2)
10291038
@serializable.view(SchemaVersion1Dot3)
10301039
@serializable.view(SchemaVersion1Dot4)
1040+
@serializable.view(SchemaVersion1Dot5)
10311041
@serializable.type_mapping(LicenseRepositoryHelper)
10321042
@serializable.xml_sequence(10)
10331043
def licenses(self) -> LicenseRepository:
@@ -1098,6 +1108,7 @@ def purl(self, purl: Optional[PackageURL]) -> None:
10981108
@serializable.view(SchemaVersion1Dot2)
10991109
@serializable.view(SchemaVersion1Dot3)
11001110
@serializable.view(SchemaVersion1Dot4)
1111+
@serializable.view(SchemaVersion1Dot5)
11011112
@serializable.xml_sequence(14)
11021113
def swid(self) -> Optional[Swid]:
11031114
"""
@@ -1127,6 +1138,7 @@ def modified(self, modified: bool) -> None:
11271138
@serializable.view(SchemaVersion1Dot2)
11281139
@serializable.view(SchemaVersion1Dot3)
11291140
@serializable.view(SchemaVersion1Dot4)
1141+
@serializable.view(SchemaVersion1Dot5)
11301142
@serializable.xml_sequence(16)
11311143
def pedigree(self) -> Optional[Pedigree]:
11321144
"""
@@ -1147,6 +1159,7 @@ def pedigree(self, pedigree: Optional[Pedigree]) -> None:
11471159
@serializable.view(SchemaVersion1Dot2)
11481160
@serializable.view(SchemaVersion1Dot3)
11491161
@serializable.view(SchemaVersion1Dot4)
1162+
@serializable.view(SchemaVersion1Dot5)
11501163
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
11511164
@serializable.xml_sequence(17)
11521165
def external_references(self) -> 'SortedSet[ExternalReference]':
@@ -1166,6 +1179,7 @@ def external_references(self, external_references: Iterable[ExternalReference])
11661179
@property
11671180
@serializable.view(SchemaVersion1Dot3)
11681181
@serializable.view(SchemaVersion1Dot4)
1182+
@serializable.view(SchemaVersion1Dot5)
11691183
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property')
11701184
@serializable.xml_sequence(18)
11711185
def properties(self) -> 'SortedSet[Property]':
@@ -1203,6 +1217,7 @@ def components(self, components: Iterable['Component']) -> None:
12031217
@property
12041218
@serializable.view(SchemaVersion1Dot3)
12051219
@serializable.view(SchemaVersion1Dot4)
1220+
@serializable.view(SchemaVersion1Dot5)
12061221
@serializable.xml_sequence(20)
12071222
def evidence(self) -> Optional[ComponentEvidence]:
12081223
"""
@@ -1219,6 +1234,7 @@ def evidence(self, evidence: Optional[ComponentEvidence]) -> None:
12191234

12201235
@property
12211236
@serializable.view(SchemaVersion1Dot4)
1237+
@serializable.view(SchemaVersion1Dot5)
12221238
@serializable.xml_sequence(21)
12231239
def release_notes(self) -> Optional[ReleaseNotes]:
12241240
"""

cyclonedx/model/service.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from cyclonedx.serialization import BomRefHelper, LicenseRepositoryHelper
2222

23-
from ..schema.schema import SchemaVersion1Dot3, SchemaVersion1Dot4
23+
from ..schema.schema import SchemaVersion1Dot3, SchemaVersion1Dot4, SchemaVersion1Dot5
2424
from . import ComparableTuple, DataClassification, ExternalReference, OrganizationalEntity, Property, XsUri
2525
from .bom_ref import BomRef
2626
from .dependency import Dependable
@@ -291,6 +291,7 @@ def services(self, services: Iterable['Service']) -> None:
291291

292292
@property
293293
@serializable.view(SchemaVersion1Dot4)
294+
@serializable.view(SchemaVersion1Dot5)
294295
@serializable.xml_sequence(14)
295296
def release_notes(self) -> Optional[ReleaseNotes]:
296297
"""
@@ -308,6 +309,7 @@ def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None:
308309
@property
309310
@serializable.view(SchemaVersion1Dot3)
310311
@serializable.view(SchemaVersion1Dot4)
312+
@serializable.view(SchemaVersion1Dot5)
311313
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property')
312314
@serializable.xml_sequence(12)
313315
def properties(self) -> 'SortedSet[Property]':

cyclonedx/output/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from .json import Json as JsonOutputter
3535
from .xml import Xml as XmlOutputter
3636

37-
LATEST_SUPPORTED_SCHEMA_VERSION = SchemaVersion.V1_4
37+
LATEST_SUPPORTED_SCHEMA_VERSION = SchemaVersion.V1_5
3838

3939

4040
class BaseOutput(ABC):

cyclonedx/output/json.py

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
SchemaVersion1Dot2,
3030
SchemaVersion1Dot3,
3131
SchemaVersion1Dot4,
32+
SchemaVersion1Dot5,
3233
)
3334
from . import BaseOutput, BomRefDiscriminator
3435

@@ -117,7 +118,14 @@ def _get_schema_uri(self) -> str:
117118
return 'http://cyclonedx.org/schema/bom-1.4.schema.json'
118119

119120

121+
class JsonV1Dot5(Json, SchemaVersion1Dot5):
122+
123+
def _get_schema_uri(self) -> str:
124+
return 'http://cyclonedx.org/schema/bom-1.5.schema.json'
125+
126+
120127
BY_SCHEMA_VERSION: Dict[SchemaVersion, Type[Json]] = {
128+
SchemaVersion.V1_5: JsonV1Dot5,
121129
SchemaVersion.V1_4: JsonV1Dot4,
122130
SchemaVersion.V1_3: JsonV1Dot3,
123131
SchemaVersion.V1_2: JsonV1Dot2,

cyclonedx/output/xml.py

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
SchemaVersion1Dot2,
3030
SchemaVersion1Dot3,
3131
SchemaVersion1Dot4,
32+
SchemaVersion1Dot5,
3233
)
3334
from . import BaseOutput, BomRefDiscriminator
3435

@@ -114,7 +115,12 @@ class XmlV1Dot4(Xml, SchemaVersion1Dot4):
114115
pass
115116

116117

118+
class XmlV1Dot5(Xml, SchemaVersion1Dot5):
119+
pass
120+
121+
117122
BY_SCHEMA_VERSION: Dict[SchemaVersion, Type[Xml]] = {
123+
SchemaVersion.V1_5: XmlV1Dot5,
118124
SchemaVersion.V1_4: XmlV1Dot4,
119125
SchemaVersion.V1_3: XmlV1Dot3,
120126
SchemaVersion.V1_2: XmlV1Dot2,

cyclonedx/schema/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class SchemaVersion(Enum):
5353
my_sv = SchemaVersion.V1_3
5454
"""
5555

56+
V1_5 = (1, 5)
5657
V1_4 = (1, 4)
5758
V1_3 = (1, 3)
5859
V1_2 = (1, 2)

cyclonedx/schema/_res/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ Currently using version
1313
| [`bom-1.2.SNAPSHOT.xsd`](bom-1.2.SNAPSHOT.xsd) | applied changes: 1 |
1414
| [`bom-1.3.SNAPSHOT.xsd`](bom-1.3.SNAPSHOT.xsd) | applied changes: 1 |
1515
| [`bom-1.4.SNAPSHOT.xsd`](bom-1.4.SNAPSHOT.xsd) | applied changes: 1 |
16+
| [`bom-1.5.SNAPSHOT.xsd`](bom-1.5.SNAPSHOT.xsd) | applied changes: 1 |
1617
| [`bom-1.2.SNAPSHOT.schema.json`](bom-1.2.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
1718
| [`bom-1.3.SNAPSHOT.schema.json`](bom-1.3.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
1819
| [`bom-1.4.SNAPSHOT.schema.json`](bom-1.4.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
20+
| [`bom-1.5.SNAPSHOT.schema.json`](bom-1.5.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
1921
| [`bom-1.2-strict.SNAPSHOT.schema.json`](bom-1.2-strict.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
2022
| [`bom-1.3-strict.SNAPSHOT.schema.json`](bom-1.3-strict.SNAPSHOT.schema.json) | applied changes: 2,3,4,5 |
2123
| [`spdx.SNAPSHOT.xsd`](spdx.SNAPSHOT.xsd) | |

cyclonedx/schema/_res/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
__DIR = dirname(__file__)
2929

3030
BOM_XML: Dict[SchemaVersion, Optional[str]] = {
31+
SchemaVersion.V1_5: join(__DIR, 'bom-1.5.SNAPSHOT.xsd'),
3132
SchemaVersion.V1_4: join(__DIR, 'bom-1.4.SNAPSHOT.xsd'),
3233
SchemaVersion.V1_3: join(__DIR, 'bom-1.3.SNAPSHOT.xsd'),
3334
SchemaVersion.V1_2: join(__DIR, 'bom-1.2.SNAPSHOT.xsd'),
@@ -36,6 +37,7 @@
3637
}
3738

3839
BOM_JSON: Dict[SchemaVersion, Optional[str]] = {
40+
SchemaVersion.V1_5: join(__DIR, 'bom-1.5.SNAPSHOT.schema.json'),
3941
SchemaVersion.V1_4: join(__DIR, 'bom-1.4.SNAPSHOT.schema.json'),
4042
SchemaVersion.V1_3: join(__DIR, 'bom-1.3.SNAPSHOT.schema.json'),
4143
SchemaVersion.V1_2: join(__DIR, 'bom-1.2.SNAPSHOT.schema.json'),
@@ -46,6 +48,7 @@
4648

4749
BOM_JSON_STRICT: Dict[SchemaVersion, Optional[str]] = {
4850
# >= v1.4 is already strict - no special file here
51+
SchemaVersion.V1_5: join(__DIR, 'bom-1.5.SNAPSHOT.schema.json'),
4952
SchemaVersion.V1_4: join(__DIR, 'bom-1.4.SNAPSHOT.schema.json'),
5053
# <= 1.3 need special files
5154
SchemaVersion.V1_3: join(__DIR, 'bom-1.3-strict.SNAPSHOT.schema.json'),

0 commit comments

Comments
 (0)