Skip to content

Added citation support and test cases. #630

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

Open
wants to merge 5 commits into
base: 1.7-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions schema/bom-1.7.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ message Bom {
repeated Declarations declarations = 14;
// A collection of reusable objects that are defined and may be used elsewhere in the BOM.
repeated Definition definitions = 15;
// Details a specific attribution of data within the BOM to a contributing entity or process.
repeated Citation citations = 16;
}

enum Classification {
Expand Down Expand Up @@ -320,6 +322,8 @@ enum ExternalReferenceType {
EXTERNAL_REFERENCE_TYPE_RFC_9116 = 41;
// Reference to release notes
EXTERNAL_REFERENCE_TYPE_RELEASE_NOTES = 42;
// A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM.
EXTERNAL_REFERENCE_TYPE_CITATION = 43;
}

enum HashAlg {
Expand Down Expand Up @@ -2393,3 +2397,18 @@ message CryptoProperties {
// The object identifier (OID) of the cryptographic asset.
optional string oid = 6;
}

message Citation {
// Optional unique identifier for the citation
optional string bom_ref = 1;
// One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies.
repeated string pointer = 2;
// Timestamp when the attribution was made or the information was supplied.
google.protobuf.Timestamp timestamp = 3;
// The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information.
optional string attributed_to = 4;
// An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data.
optional string process = 5;
// An optional description or comment about the context or quality of the data attribution.
optional string note = 6;
}
63 changes: 63 additions & 0 deletions schema/bom-1.7.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,13 @@
}
}
},
"citations": {
"type": "array",
"items": {"$ref": "#/definitions/citation"},
"uniqueItems": true,
"title": "Citations",
"description": "A list of attributions indicating which entity supplied information for specific fields within the BOM."
},
"properties": {
"type": "array",
"title": "Properties",
Expand Down Expand Up @@ -1805,6 +1812,7 @@
"electronic-signature",
"digital-signature",
"rfc-9116",
"citation",
"other"
],
"meta:enum": {
Expand Down Expand Up @@ -1850,6 +1858,7 @@
"electronic-signature": "An e-signature is commonly a scanned representation of a written signature or a stylized script of the person's name.",
"digital-signature": "A signature that leverages cryptography, typically public/private key pairs, which provides strong authenticity verification.",
"rfc-9116": "Document that complies with [RFC 9116](https://www.ietf.org/rfc/rfc9116.html) (A File Format to Aid in Security Vulnerability Disclosure)",
"citation": "A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM.",
"other": "Use this if no other types accurately describe the purpose of the external reference."
}
},
Expand Down Expand Up @@ -5725,6 +5734,60 @@
"translation",
"object-detection"
]
},
"citation": {
"type": "object",
"title": "Citation",
"description": "Details a specific attribution of data within the BOM to a contributing entity or process.",
"additionalProperties": false,
"properties": {
"bom-ref": {
"$ref": "#/definitions/refType",
"title": "BOM Reference"
},
"attributedTo": {
"$ref": "#/definitions/refLinkType",
"title": "Attributed To",
"description": "The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information."
},
"pointers": {
"type": "array",
"items": {
"type": "string",
"title": "Field Reference",
"description": "A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations."
},
"minItems": 1,
"title": "Field References",
"description": "One or more [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies."
},
"timestamp": {
"type": "string",
"format": "date-time",
"title": "Timestamp",
"description": "The date and time when the attribution was made or the information was supplied."
},
"process": {
"$ref": "#/definitions/refLinkType",
"title": "Process Reference",
"description": "An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data."
},
"note": {
"type": "string",
"title": "Note",
"description": "An optional description or comment about the context or quality of the data attribution."
},
"signature": {
"$ref": "#/definitions/signature",
"title": "Signature",
"description": "An optional digital signature verifying the authenticity or integrity of the attribution."
}
},
"required": ["pointers", "timestamp"],
"anyOf": [
Copy link
Member

@jkowalleck jkowalleck May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


what is this anyOf supposed to mean?
if i understand it correct, it means, atleast one of the following is required. ...

I missed a respective part in the XML and in the ProtoBuf - I would expect to see at least a text expressing this requirement.

i suggest

  • adding a textual annotation the ProtoBuf that expresses that rule
  • adding a textual annotation the XML that expresses that rule. or add a choice if technically possible.
  • providing proper examples/test-data for valid and invalid showcases

{ "required": ["attributedTo"] },
{ "required": ["process"] }
]
}
}
}
94 changes: 94 additions & 0 deletions schema/bom-1.7.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,11 @@ limitations under the License.
<xs:documentation>Document that complies with RFC-9116 (A File Format to Aid in Security Vulnerability Disclosure)</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="citation">
<xs:annotation>
<xs:documentation>A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="other">
<xs:annotation>
<xs:documentation>Use this if no other types accurately describe the purpose of the external reference</xs:documentation>
Expand Down Expand Up @@ -8349,6 +8354,90 @@ limitations under the License.
</xs:sequence>
</xs:complexType>

<xs:complexType name="citationsType">
<xs:sequence>
<xs:element name="citation" type="bom:citationType" minOccurs="1" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>
Details a specific attribution of data within the BOM to a contributing entity or process.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="citationType">
<xs:sequence>
<xs:element name="pointers" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="pointer" type="xs:string" minOccurs="1" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>
A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="timestamp" type="xs:dateTime" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
The date and time when the attribution was made or the information was supplied.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="attributedTo" type="bom:refLinkType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="process" type="bom:refLinkType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="note" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
An optional description or comment about the context or quality of the data attribution.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>
Allows any undeclared elements as long as the elements are placed in a different namespace.
</xs:documentation>
</xs:annotation>
</xs:any>
</xs:sequence>
<xs:attribute name="bom-ref" type="bom:refType" use="optional">
<xs:annotation>
<xs:documentation>
An optional identifier which can be used to reference the object elsewhere in the BOM.
Uniqueness is enforced within all elements and children of the root-level bom element.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:anyAttribute namespace="##other" processContents="lax">
<xs:annotation>
<xs:documentation>User-defined attributes may be used on this element as long as they
do not have the same name as an existing attribute used by the schema.</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>

<xs:element name="bom">
<xs:complexType>
<xs:sequence>
Expand Down Expand Up @@ -8430,6 +8519,11 @@ limitations under the License.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="citations" type="bom:citationsType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A list of attributions indicating which entity supplied information for specific fields within the BOM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>
Expand Down
77 changes: 77 additions & 0 deletions tools/src/test/resources/1.7/valid-citations-1.7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2025-05-01T14:23:00Z",
"authors": [
{
"bom-ref": "person-1",
"name": "Alice Example",
"email": "[email protected]"
}
]
},
"components": [
{
"type": "library",
"bom-ref": "component-1",
"name": "example-lib",
"version": "1.2.3",
"licenses": [
{
"license": {
"id": "Apache-2.0"
}
}
]
}
],
"citations": [
{
"bom-ref": "citation-1",
"pointers": [ "/components/0/name" ],
"timestamp": "2025-05-01T14:00:00Z",
"attributedTo": "person-1",
"note": "Manually entered by Alice Example"
},
{
"bom-ref": "citation-2",
"pointers": [ "/components/0/licenses/0/license/id" ],
"timestamp": "2025-05-01T14:05:00Z",
"attributedTo": "scan-tool-1",
"process": "task-license-scan",
"note": "Auto-detected by license scanner tool"
}
],
"formulation": [
{
"components": [
{
"bom-ref": "scan-tool-1",
"type": "application",
"name": "My Scan Tool"
}
],
"bom-ref": "workflow-1",
"workflows": [
{
"bom-ref": "workflow-1",
"uid": "259bae74-5ec4-4de8-9386-c91b1f7719b8",
"name": "My workflow",
"tasks": [
{
"bom-ref": "task-license-scan",
"uid": "6d75f8d6-a008-41cf-8b65-c4129fc249f9",
"taskTypes": [ "scan" ],
"description": "License scan of the source files using OpenSourceScanner v2.1"
}
],
"taskTypes": [ "scan" ]
}
]
}
]
}
75 changes: 75 additions & 0 deletions tools/src/test/resources/1.7/valid-citations-1.7.textproto
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# proto-file: schema/bom-1.7.proto
# proto-message: Bom

spec_version: "1.7"
version: 1
serial_number: "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79"

metadata {
timestamp {
seconds: 1746118980
nanos: 0
}
authors {
bom_ref: "person-1"
name: "Alice Example"
email: "[email protected]"
}
}

components {
bom_ref: "component-1"
type: CLASSIFICATION_LIBRARY
name: "example-lib"
version: "1.2.3"
licenses {
license {
id: "Apache-2.0"
}
}
}

citations [
{
bom_ref: "citation-1"
pointer: "/components/0/name"
timestamp: {
seconds: 1746108000
nanos: 0
}
attributed_to: "person-1"
note: "Manually entered by Alice Example"
},
{
bom_ref: "citation-2"
pointer: "/components/0/licenses/0/license/id"
timestamp: {
seconds: 1746108000
nanos: 0
}
attributed_to: "scan-tool-1"
process: "task-license-scan"
note: "Auto-detected by license scanner tool"
}
]

formulation {
bom_ref: "workflow-1"
components {
bom_ref: "scan-tool-1"
type: CLASSIFICATION_APPLICATION
name: "My Scan Tool"
}
workflows {
bom_ref: "workflow-1"
uid: "259bae74-5ec4-4de8-9386-c91b1f7719b8"
name: "My workflow"
taskTypes: TASK_TYPE_SCAN
tasks {
bom_ref: "task-license-scan"
uid: "6d75f8d6-a008-41cf-8b65-c4129fc249f9"
taskTypes: TASK_TYPE_SCAN
description: "License scan of the source files using OpenSourceScanner v2.1"
}
}
}
Loading