A model card tells people what a model is for, how it was evaluated and where it fails. A dataset card explains how data was collected, labelled and filtered, and what bias it carries. An AIBOM is a machine readable inventory of the model, datasets, dependencies, hashes and licences, in CycloneDX or SPDX 3. You need all three.
The cards carry judgement and narrative; the AIBOM carries identity and relationships that tools can verify. This post maps common questions to the document built to answer them, gives a field level crosswalk between the cards and both AIBOM formats, lines all three up against the EU AI Act documentation annexes, and shows how to generate the AIBOM from the cards so nobody types the same facts twice.
Key takeaways
- Model cards come from a 2018 research proposal and today are usually a README with a YAML metadata block. They answer "should I use this model, for what, and where does it break?"
- Dataset cards answer "where did this data come from, who labelled it, what is missing or skewed?"
- AIBOMs answer "which exact model file, trained on which datasets, derived from which parent model, under which licences?" CycloneDX uses the
modelCardobject anddatacomponents; SPDX 3 uses the AI and Dataset profiles. - Only an AIBOM gives you hashes, dependency edges and machine checkable licences. Only a card gives you intended use, evaluation context and caveats written for people.
- The EU AI Act Annex IV and Annex XI mix inventory items, which an AIBOM carries well, with design rationale and evaluation narrative, which belong in cards and the wider technical file.
- Generate, do not retype. Open source tools can turn Hugging Face style model cards into CycloneDX AIBOMs, and a short script does the same for internal models.
What each document is for, who writes it, and whether a machine can read it
Before mapping fields, it helps to be precise about what each document is and who is expected to produce it.
| Model card | Dataset card | AIBOM (ML-BOM) | |
|---|---|---|---|
| Main job | Explain a trained model to the people who will use or review it | Explain a dataset to the people who will train on it or review it | Inventory an AI system's components and their relationships so tools can check them |
| Primary reader | Engineers adopting the model, reviewers, risk and compliance staff | Data scientists, reviewers, privacy staff | Security tooling, procurement, auditors, incident responders, policy engines |
| Usual author | The team that trained or fine tuned the model | The team that collected or curated the data | Generated by a build or inventory tool, then reviewed by the producing team |
| Format | Markdown README, often with a YAML metadata block | Markdown README, often with a YAML metadata block | CycloneDX (JSON, XML, Protocol Buffers) or SPDX 3 (JSON-LD) |
| Machine readable | Only the YAML block; the body is prose | Only the YAML block; the body is prose | Yes, validated against a published schema |
| Standard | Research proposal (2018); hosting platform conventions | Research proposal (2018, journal 2021); hosting platform conventions | CycloneDX ML-BOM (since 1.5); SPDX 3.0 AI and Dataset profiles |
Model cards
The model card idea comes from "Model Cards for Model Reporting" by Margaret Mitchell and colleagues, first posted to arXiv on 5 October 2018. The abstract describes short documents that accompany trained models, report benchmarked evaluation across relevant groups and state the context the model is meant for. The paper proposes nine sections: Model Details, Intended Use, Factors, Metrics, Evaluation Data, Training Data, Quantitative Analyses, Ethical Considerations, and Caveats and Recommendations.
Most model cards you meet today are README files on a model hub. The Hugging Face Hub documentation describes a model card as a Markdown file with a YAML section at the top. The Hub template keeps the spirit of the paper with sections such as Uses (direct, downstream and out of scope), Bias, Risks and Limitations, Training Details, Evaluation and Environmental Impact. The YAML block holds fields such as license, datasets, base_model and pipeline_tag, and it is the only part a tool can parse reliably.
For the reviewer's side, see the model card fields to read before adopting a model.
Dataset cards and datasheets
"Datasheets for Datasets" by Timnit Gebru and colleagues was first posted to arXiv on 23 March 2018 and published in Communications of the ACM in December 2021. Its argument borrows from electronics, where every component ships with a datasheet: every dataset should come with a document covering its motivation, composition, collection process and recommended uses.
The Hub's dataset card is the common practical form. Its template has sections for Dataset Details, Uses (direct and out of scope), Dataset Structure, Dataset Creation (curation rationale, source data, collection and processing, who produced the source data, annotations, who the annotators are, personal and sensitive information), Bias, Risks and Limitations, and contact and citation details. Like the model card, it is Markdown with a YAML metadata block that carries license, task_categories, language and size tags.
For the supply chain reviewer's view of these fields, see what a dataset card is and which fields matter for supply chain review.
AIBOMs
An AIBOM, which CycloneDX calls an ML-BOM, is a bill of materials for an AI system. The CycloneDX ML-BOM capability page says it represents models, datasets and their dependencies, including dataset provenance, training methodology and framework configuration. The machine-learning-model and data component types and the modelCard object first appear in the CycloneDX 1.5 schema; the 1.4 schema has no modelCard at all. The structure is unchanged in 1.6 and 1.7: the modelCard object has the same four top level keys in both schemas.
SPDX 3.0 took a different route. Instead of a nested card object, it adds two profiles. The AI profile defines an AIPackage class, a subclass of the software Package, with properties such as typeOfModel, hyperparameter, metric, limitation, informationAboutTraining, energyConsumption and safetyRiskAssessment. The Dataset profile defines DatasetPackage with datasetType, datasetSize, dataCollectionProcess, intendedUse, knownBias, hasSensitivePersonalInformation and more. Models and datasets are linked with relationship types such as trainedOn and testedOn.
The OWASP GenAI Security Project runs an AIBOM initiative aimed at turning the AIBOM into practical, community driven implementation with open source tooling and completeness assessment. For background on why AIBOMs and cards emerged together, see AI SBOMs and model cards: transparency in 2025.
Which questions each document answers
Write down the question you have been asked, then check which document was designed to hold the answer.
| Question | Model card | Dataset card | AIBOM |
|---|---|---|---|
| What is this model intended to be used for, and by whom? | Yes, the main source | No | Short strings only (considerations.users, useCases; SPDX informationAboutApplication) |
| What should it not be used for? | Yes (out of scope use) | No | Only as a limitation string |
| How well does it perform, on which slices, measured how? | Yes, with narrative and context | No | Metric values and slices (performanceMetrics; SPDX metric) without the story |
| Which exact file is deployed? | No | No | Yes, by hash and identifier |
| Which datasets trained and tested it? | Named, often loosely | Describes one dataset | Yes, as typed references and relationships (trainedOn, testedOn) |
| Which base model was it fine tuned from? | Named in YAML (base_model) | No | Yes (pedigree.ancestors; SPDX lineage relationships such as descendantOf) |
| Under which licence can I use the model and the data? | Free text or a short id | Free text or a short id | Machine checkable licence expressions; SPDX 3 AI and Dataset profiles require both declared and concluded licence relationships |
| How was the data collected, filtered and labelled? | Briefly, at best | Yes, the main source | Short strings (dataCollectionProcess, dataPreprocessing) |
| Does the data contain personal information? | Rarely | Yes | Yes as a flag (hasSensitivePersonalInformation; CycloneDX sensitiveData) |
| Which libraries and runtimes does the system depend on? | Sometimes in technical specifications | No | Yes, as components and dependency edges, same as any SBOM |
| Is the deployed model affected by a newly disclosed vulnerability in its runtime? | No | No | Yes, when the AIBOM sits inside or links to the application SBOM |
| Who is accountable for the data? | Contact line | Contact line | governance owners, stewards and custodians (CycloneDX); originatedBy and suppliedBy (SPDX) |
Questions only an AIBOM answers
Four kinds of question can only be answered reliably by a bill of materials.
Identity. "Is the model in production the one that was evaluated?" needs a cryptographic hash. Cards do not carry one. CycloneDX uses hashes on the component; SPDX 3 uses verifiedUsing on the package.
Dependencies. "What does this model need to run, and what depends on it?" needs dependency edges. An AIBOM records the model as a component the application depends on, and the datasets and parent models behind it, so a query can walk the graph.
Provenance. A card's YAML may name the parent model and datasets, but names are not resolvable identifiers. An AIBOM stores typed references: CycloneDX pedigree.ancestors and modelParameters.datasets pointing at data components by bom-ref; SPDX 3 relationships between elements with stable IRIs.
Licences as data. "Can we ship this commercially?" needs licence expressions a policy engine can evaluate for the model and every dataset. The SPDX 3 AI profile requires every AIPackage to have exactly one hasDeclaredLicense and exactly one hasConcludedLicense relationship, and the Dataset profile says the same for every DatasetPackage. Cards carry a licence string, and many say "other".
Questions only a card answers
Intended use, in context. Both formats have short fields for users and use cases, but neither carries the reasoning: why this task, which deployments were rejected, what an integrator must not do.
Evaluation narrative. A metric of 0.91 means little without the test set, the slicing logic and the conditions. The original paper's emphasis on disaggregated evaluation is the clearest example. An AIBOM holds the number and a slice label; the card holds the method and its caveats.
Limitations and labelling. Useful limitation statements run to paragraphs, and a dataset card explains who annotated the data and how consent was handled. The AIBOM string fields for these are pointers, not substitutes.
Questions both can answer, and which copy wins
Licence, base model, dataset names, task and language appear in both. When they disagree, treat the AIBOM as the record and the card as the explanation, because the AIBOM is generated from the artifact and validated against a schema. Better still, generate those overlapping AIBOM fields from the card's YAML so they cannot disagree. The walkthrough below shows how.
Crosswalk: model card sections to CycloneDX modelCard and SPDX 3 AI fields
The table maps each of the nine sections in the original model card paper, plus the extra sections in the Hub template, to the nearest field in CycloneDX 1.7 and SPDX 3.0.1. Field names come from the CycloneDX 1.7 JSON schema and the SPDX 3.0.1 AIPackage model page. "No field" means there is no dedicated property; most teams use CycloneDX properties (name and value pairs) or SPDX comment, or link to the card.
| Model card section | CycloneDX 1.7 | SPDX 3.0.1 AI profile |
|---|---|---|
| Model details: name, version, developer | Component name, version, supplier, manufacturer, authors | name, software_packageVersion, suppliedBy, originatedBy, releaseTime |
| Model details: model type and architecture | modelParameters.approach.type (supervised, unsupervised, reinforcement-learning, semi-supervised, self-supervised), architectureFamily, modelArchitecture | ai_typeOfModel |
| Model details: licence | Component licenses | hasDeclaredLicense and hasConcludedLicense relationships (both required by the profile) |
| Model details: fine tuned from | pedigree.ancestors | Lineage relationships between packages; ai_informationAboutTraining for prose |
| Intended use: primary uses and users | considerations.useCases, considerations.users | ai_informationAboutApplication, ai_domain |
| Intended use: out of scope uses | No dedicated field; considerations.technicalLimitations | ai_limitation |
| Task, inputs and outputs | modelParameters.task, inputs[].format, outputs[].format | ai_typeOfModel, ai_informationAboutApplication |
| Factors (groups, instrumentation, environment) | performanceMetrics[].slice, considerations.fairnessAssessments[].groupAtRisk | No dedicated field |
| Metrics and thresholds | quantitativeAnalysis.performanceMetrics[] (type, value, slice, confidenceInterval) | ai_metric, ai_metricDecisionThreshold |
| Evaluation data | modelParameters.datasets[] (data component or reference) | testedOn relationship to a DatasetPackage |
| Training data | modelParameters.datasets[] | trainedOn relationship to a DatasetPackage; ai_informationAboutTraining |
| Training procedure and preprocessing | No dedicated field | ai_modelDataPreprocessing |
| Hyperparameters | No dedicated field (use properties) | ai_hyperparameter (key and value entries) |
| Quantitative analyses and charts | quantitativeAnalysis.graphics | No dedicated field |
| Ethical considerations | considerations.ethicalConsiderations[] (name, mitigationStrategy) | ai_safetyRiskAssessment (serious, high, medium, low) is the nearest, but it is a rating, not a list |
| Fairness | considerations.fairnessAssessments[] (groupAtRisk, benefits, harms, mitigationStrategy) | No dedicated field |
| Caveats and recommendations | considerations.technicalLimitations, performanceTradeoffs | ai_limitation |
| Explainability | No dedicated field | ai_modelExplainability |
| Personal data used | Not on the model; on the dataset (sensitiveData) | ai_useSensitivePersonalInformation |
| Human in the loop or autonomy | No dedicated field | ai_autonomyType (yes, no, noAssertion) |
| Environmental impact | considerations.environmentalConsiderations.energyConsumptions | ai_energyConsumption |
| Standards the model complies with | No dedicated field | ai_standardCompliance |
| Link back to the card itself | externalReferences of type model-card | externalRef on the package |
CycloneDX is closer to the shape of the original paper, with nested objects for considerations, fairness and quantitative analysis, and an external reference type named model-card. SPDX 3 is flatter and leans on relationships, but it has fields CycloneDX lacks: hyperparameters, decision thresholds, explainability, autonomy and a safety risk rating.
Neither replaces the card. Every field that maps to a narrative section is a string or a list of strings: good for search, policy and summary, poor for a page of evaluation discussion. Fill the structured fields, keep them short, and link to the card.
Crosswalk: dataset card sections to SPDX 3 Dataset fields and CycloneDX data components
The same exercise for datasets. Field names come from the SPDX 3.0.1 DatasetPackage page and the CycloneDX 1.7 componentData definition.
| Dataset card section | SPDX 3.0.1 Dataset profile | CycloneDX 1.7 |
|---|---|---|
| Dataset description and summary | summary, description | Component description; data[].description |
| Curated by, shared by | originatedBy (required for datasets), suppliedBy | Component supplier, authors; data[].governance owners, stewards, custodians |
| Dataset sources (repository, paper) | software_downloadLocation, homePage, externalRef | data[].contents.url, component externalReferences |
| Licence | hasDeclaredLicense and hasConcludedLicense (both required by the profile) | Component licenses |
| Direct use | dataset_intendedUse | No dedicated field; data[].description |
| Out of scope use | No dedicated field | No dedicated field |
| Dataset structure and modality | dataset_datasetType (required; values such as structured, numeric, text, categorical, graph, timeseries, timestamp, sensor, image, syntactic, audio, video) | data[].type (source-code, configuration, dataset, definition, other) |
| Size | dataset_datasetSize (bytes or count, as a non negative integer) | No dedicated field; description or properties |
| Curation rationale | No dedicated field; comment | No dedicated field |
| Data collection and processing | dataset_dataCollectionProcess, dataset_dataPreprocessing, dataset_sensor | No dedicated field |
| Who produced the source data | originatedBy | data[].governance |
| Annotations and annotators | No dedicated field; dataset_dataPreprocessing or comment | No dedicated field |
| Personal and sensitive information | dataset_hasSensitivePersonalInformation, dataset_anonymizationMethodUsed, dataset_confidentialityLevel (red, amber, green, clear) | data[].sensitiveData, data[].classification |
| Bias, risks and limitations | dataset_knownBias, dataset_datasetNoise | No dedicated field; description |
| How to get it | dataset_datasetAvailability (clickthrough, directDownload, query, registration, scrapingScript) | data[].contents (attachment or url) |
| How it is updated | dataset_datasetUpdateMechanism | No dedicated field |
| When it was built and released | builtTime and releaseTime (both required for datasets) | Component version; BOM metadata.timestamp |
| Integrity | verifiedUsing | Component hashes |
Here SPDX 3 is richer: the Dataset profile follows the questions a datasheet asks. CycloneDX's componentData is lighter, with stronger governance roles and data classification. Neither has a field for annotation process or curation rationale. For the data governance angle, see AI-BOMs and EU AI Act Article 10 data governance.
A minimal AIBOM, twice: CycloneDX 1.7 and SPDX 3.0.1
Below is the same small system in both formats: an application that depends on a fine tuned text classifier, trained on one internal dataset. Names, hashes and URLs are examples.
CycloneDX 1.7
This document validates against the CycloneDX 1.7 JSON schema (bom-1.7.schema.json from the CycloneDX specification repository, with its referenced SPDX licence and JSF schemas). We checked it with a JSON Schema validator on 23 October 2026, and confirmed the validator rejects an unknown property in modelParameters.
{
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-10-23T09:00:00Z",
"component": {
"type": "application",
"bom-ref": "app-ticket-router",
"name": "ticket-router",
"version": "2.4.0"
}
},
"components": [
{
"type": "machine-learning-model",
"bom-ref": "model-ticket-classifier",
"supplier": { "name": "Example Corp" },
"name": "ticket-classifier",
"version": "2.4.0",
"hashes": [
{ "alg": "SHA-256", "content": "9f2c4e1a7b3d5f60812a4c6e8b0d2f4a6c8e0b2d4f6a8c0e2b4d6f8a0c2e4b6d" }
],
"licenses": [ { "license": { "id": "Apache-2.0" } } ],
"pedigree": {
"ancestors": [
{ "type": "machine-learning-model", "name": "example-base-encoder", "version": "1.0.0" }
]
},
"externalReferences": [
{ "type": "model-card", "url": "https://models.example.com/ticket-classifier/2.4.0/README.md" }
],
"modelCard": {
"modelParameters": {
"approach": { "type": "supervised" },
"task": "text-classification",
"architectureFamily": "transformer",
"modelArchitecture": "encoder-only transformer, 12 layers",
"datasets": [ { "ref": "data-tickets-2025" } ],
"inputs": [ { "format": "text/plain" } ],
"outputs": [ { "format": "application/json" } ]
},
"quantitativeAnalysis": {
"performanceMetrics": [
{ "type": "macro-F1", "value": "0.91", "slice": "held-out test split, English tickets" }
]
},
"considerations": {
"users": [ "Support operations staff" ],
"useCases": [ "Suggest a queue for an inbound support ticket; a human confirms" ],
"technicalLimitations": [ "Trained on English text only; accuracy on other languages is untested" ],
"ethicalConsiderations": [
{ "name": "Misrouting urgent tickets", "mitigationStrategy": "Tickets flagged as outages bypass the model" }
]
}
}
},
{
"type": "data",
"bom-ref": "data-tickets-2025",
"name": "tickets-2025-labelled",
"version": "2025.12",
"data": [
{
"type": "dataset",
"name": "tickets-2025-labelled",
"description": "120,000 labelled support tickets, January to December 2025, training split",
"classification": "confidential",
"sensitiveData": [ "Email addresses and phone numbers removed before labelling" ],
"governance": {
"owners": [ { "organization": { "name": "Example Corp Support Operations" } } ]
}
}
]
}
],
"dependencies": [
{ "ref": "app-ticket-router", "dependsOn": [ "model-ticket-classifier" ] },
{ "ref": "model-ticket-classifier", "dependsOn": [ "data-tickets-2025" ] },
{ "ref": "data-tickets-2025" }
]
}
The dataset is a first class data component with its own bom-ref, so the model's datasets entry is a reference, not a copy. The card is linked through a model-card external reference rather than inlined. The dependency graph runs application to model to dataset, so "which applications are downstream of this dataset" is answered the same way as for a library.
SPDX 3.0.1
This document validates against the SPDX 3.0.1 JSON schema (spdx-json-schema.json published at spdx.org), checked on 23 October 2026. JSON Schema validation checks structure only. The profile conformance rules, such as "exactly one declared and one concluded licence per AIPackage", are expressed in the SPDX model; the example satisfies them by hand, and a SHACL based validator from the SPDX project is the right tool to confirm them in a pipeline.
{
"@context": "https://spdx.org/rdf/3.0.1/spdx-context.jsonld",
"@graph": [
{
"type": "CreationInfo",
"@id": "_:creationinfo",
"specVersion": "3.0.1",
"created": "2026-10-23T09:00:00Z",
"createdBy": [ "https://example.com/spdx/org-example" ]
},
{
"type": "Organization",
"spdxId": "https://example.com/spdx/org-example",
"creationInfo": "_:creationinfo",
"name": "Example Corp"
},
{
"type": "ai_AIPackage",
"spdxId": "https://example.com/spdx/model-ticket-classifier-2.4.0",
"creationInfo": "_:creationinfo",
"name": "ticket-classifier",
"software_packageVersion": "2.4.0",
"software_downloadLocation": "https://models.example.com/ticket-classifier/2.4.0/",
"software_primaryPurpose": "model",
"releaseTime": "2026-10-01T00:00:00Z",
"suppliedBy": "https://example.com/spdx/org-example",
"verifiedUsing": [
{ "type": "Hash", "algorithm": "sha256", "hashValue": "9f2c4e1a7b3d5f60812a4c6e8b0d2f4a6c8e0b2d4f6a8c0e2b4d6f8a0c2e4b6d" }
],
"ai_typeOfModel": [ "encoder-only transformer" ],
"ai_domain": [ "customer support" ],
"ai_informationAboutApplication": "Suggests a queue for an inbound support ticket; a human confirms.",
"ai_limitation": "Trained on English text only; accuracy on other languages is untested.",
"ai_metric": [ { "type": "DictionaryEntry", "key": "macro-F1", "value": "0.91" } ],
"ai_hyperparameter": [ { "type": "DictionaryEntry", "key": "learning_rate", "value": "2e-5" } ],
"ai_autonomyType": "no",
"ai_safetyRiskAssessment": "low",
"ai_useSensitivePersonalInformation": "no"
},
{
"type": "dataset_DatasetPackage",
"spdxId": "https://example.com/spdx/dataset-tickets-2025",
"creationInfo": "_:creationinfo",
"name": "tickets-2025-labelled",
"software_downloadLocation": "NOASSERTION",
"software_primaryPurpose": "data",
"releaseTime": "2026-01-15T00:00:00Z",
"builtTime": "2026-01-10T00:00:00Z",
"originatedBy": [ "https://example.com/spdx/org-example" ],
"dataset_datasetType": [ "text" ],
"dataset_datasetSize": 120000,
"dataset_intendedUse": "Training and evaluating the ticket-classifier model.",
"dataset_knownBias": [ "Over-represents tickets from business-hours regions" ],
"dataset_hasSensitivePersonalInformation": "no",
"dataset_confidentialityLevel": "amber"
},
{
"type": "simplelicensing_LicenseExpression",
"spdxId": "https://example.com/spdx/license-apache-2.0",
"creationInfo": "_:creationinfo",
"simplelicensing_licenseExpression": "Apache-2.0"
},
{
"type": "simplelicensing_LicenseExpression",
"spdxId": "https://example.com/spdx/license-proprietary",
"creationInfo": "_:creationinfo",
"simplelicensing_licenseExpression": "LicenseRef-Example-Internal"
},
{
"type": "Relationship",
"spdxId": "https://example.com/spdx/rel-trained-on",
"creationInfo": "_:creationinfo",
"from": "https://example.com/spdx/model-ticket-classifier-2.4.0",
"relationshipType": "trainedOn",
"to": [ "https://example.com/spdx/dataset-tickets-2025" ]
},
{
"type": "Relationship",
"spdxId": "https://example.com/spdx/rel-model-declared",
"creationInfo": "_:creationinfo",
"from": "https://example.com/spdx/model-ticket-classifier-2.4.0",
"relationshipType": "hasDeclaredLicense",
"to": [ "https://example.com/spdx/license-apache-2.0" ]
},
{
"type": "Relationship",
"spdxId": "https://example.com/spdx/rel-model-concluded",
"creationInfo": "_:creationinfo",
"from": "https://example.com/spdx/model-ticket-classifier-2.4.0",
"relationshipType": "hasConcludedLicense",
"to": [ "https://example.com/spdx/license-apache-2.0" ]
},
{
"type": "Relationship",
"spdxId": "https://example.com/spdx/rel-data-declared",
"creationInfo": "_:creationinfo",
"from": "https://example.com/spdx/dataset-tickets-2025",
"relationshipType": "hasDeclaredLicense",
"to": [ "https://example.com/spdx/license-proprietary" ]
},
{
"type": "Relationship",
"spdxId": "https://example.com/spdx/rel-data-concluded",
"creationInfo": "_:creationinfo",
"from": "https://example.com/spdx/dataset-tickets-2025",
"relationshipType": "hasConcludedLicense",
"to": [ "https://example.com/spdx/license-proprietary" ]
}
]
}
The SPDX version reads differently. Every fact about the model is a property on one element, and every link between things is a separate Relationship element. The SPDX relationship vocabulary defines trainedOn as "the from Element has been trained on the to Element(s)" and testedOn the same way for testing, so the train and test split that CycloneDX folds into one datasets list becomes two distinct, queryable edges. The cost is length: six of the eleven graph entries (two licence expressions and four relationships) exist only to satisfy the licence rules the profiles require.
What the EU AI Act technical documentation asks for, and which document carries each item
The EU AI Act is the regulation most often cited when teams ask for AIBOMs, so it is worth being exact about what it requires and when.
Dates, as of October 2026
The European Commission's AI Act Service Desk publishes the text based on the EUR-Lex consolidated version as at 27 July 2026, marking passages added or amended by the Digital Omnibus on AI. On that text, Article 113 says the regulation applies from 2 August 2026, with exceptions: the general purpose AI model chapter (Chapter V, which includes Article 53) has applied since 2 August 2025, and the high risk requirements in Chapter III, Sections 1 to 3, which include Article 11, apply from 2 December 2027 for systems classified as high risk under Article 6(2) and Annex III, and from 2 August 2028 for systems under Article 6(1) and Annex I. If you planned around the original 2 August 2026 date for Annex III systems, check the consolidated text; our post on EU AI Act technical documentation and post market monitoring covers the documentation process itself.
Article 11 and Annex IV: high risk AI systems
Article 11(1) requires the technical documentation of a high risk AI system to be drawn up before the system is placed on the market or put into service, kept up to date, and to contain at a minimum the elements in Annex IV. The amended text also allows SMEs and small mid caps to provide Annex IV information in a simplified form that the Commission will establish.
Annex IV does not mention model cards, dataset cards or AIBOMs by name. It does mention "datasheets": point 2(d) asks for "the data requirements in terms of datasheets" describing training methodologies and training data sets. Here is how the main Annex IV items fall across the three documents.
| Annex IV item (summarised) | Best carried by | Why |
|---|---|---|
| 1(a) Intended purpose, provider name, system version and its relation to previous versions | Model card for purpose; AIBOM for version and lineage | Purpose is narrative; version and lineage are inventory |
| 1(b) Interaction with hardware, software and other AI systems not part of the system | AIBOM, embedded in the application SBOM | Dependency edges and services |
| 1(c) Versions of relevant software or firmware and version update requirements | AIBOM and SBOM | This is exactly what a bill of materials lists |
| 1(d) Forms in which the system is placed on the market (packages, downloads, APIs) | AIBOM (component types, distribution references) plus the technical file | Partly inventory, partly description |
| 1(e) to 1(h) Hardware, product photographs, user interface, instructions for use | Technical file; instructions for use | None of the three is built for these |
| 2(a) Development methods, including pre trained systems or third party tools and how they were modified | AIBOM for which pre trained model; model card for how it was adapted | Identity versus method |
| 2(b) Design specifications, key choices and rationale, what the system optimises for | Model card and design documentation | Pure narrative |
| 2(c) System architecture and how components build on each other; compute used | AIBOM and SBOM for components; model card for compute | The component graph is inventory |
| 2(d) Data requirements as datasheets: training data sets, provenance, scope, how data was obtained and selected, labelling, cleaning | Dataset cards for the narrative; AIBOM for dataset identity, provenance links and licences | The Act's own word is "datasheets" |
| 2(e) Human oversight assessment | Model card and technical file | Narrative |
| 2(g) Validation and testing procedures, test data, metrics including discriminatory impacts, signed test logs | Model card for method and results; AIBOM for test dataset identity and metric values | Signed test logs are separate records |
| 2(h) Cybersecurity measures | Security documentation, supported by the SBOM and AIBOM | The BOM is evidence, not the measure |
| 3 and 4 Capabilities, limitations, accuracy for groups, appropriateness of metrics | Model card | The original paper was written for this |
| 6 Changes through the lifecycle | AIBOM versions over time plus change log | Diffing two AIBOMs shows what changed |
| 7 Harmonised standards applied | Technical file; SPDX ai_standardCompliance can list them | Mostly a declaration |
| 5, 8 and 9 Risk management, declaration of conformity, post market monitoring plan | Separate records | Outside all three documents |
Roughly a third of Annex IV is inventory, a third narrative and a third process records. An AIBOM handles the inventory well and makes it verifiable, cards handle much of the narrative, and neither covers risk management, conformity or post market monitoring.
Article 53 and Annex XI: general purpose AI models
For providers of general purpose AI models, Article 53(1)(a) requires technical documentation of the model, "including its training and testing process and the results of its evaluation", containing at a minimum the information in Annex XI. Article 53(1)(b) requires information for downstream providers who integrate the model, with the minimum set in Annex XII. Article 53(1)(d) requires a publicly available summary of training content, using a template provided by the AI Office. Article 53(2) exempts providers of models released under a free and open source licence with public weights from points (a) and (b), but not models with systemic risk.
Annex XI Section 1 lists what every general purpose model provider must document, "as appropriate to the size and risk profile of the model".
| Annex XI Section 1 item | CycloneDX 1.7 | SPDX 3.0.1 | Card |
|---|---|---|---|
| 1(a) Tasks the model is intended to perform and the AI systems it can be integrated into | modelParameters.task, considerations.useCases | ai_informationAboutApplication, ai_domain | Model card, intended use |
| 1(b) Acceptable use policies | External reference to the policy | externalRef | Model card, out of scope use |
| 1(c) Date of release and methods of distribution | Component version, externalReferences of distribution type | releaseTime, software_downloadLocation | Model card |
| 1(d) Architecture and number of parameters | architectureFamily, modelArchitecture; parameter count in properties | ai_typeOfModel; parameter count in ai_hyperparameter or comment | Model card, technical specifications |
| 1(e) Modality and format of inputs and outputs | inputs[].format, outputs[].format | No dedicated field | Model card |
| 1(f) Licence | licenses | Declared and concluded licence relationships | Model card YAML |
| 2(a) Technical means needed to integrate the model (instructions, infrastructure, tools) | Dependencies and services in the AIBOM | Relationships | Integration guide |
| 2(b) Design specifications, training methodologies, key design choices, what the model optimises for | No dedicated field | ai_informationAboutTraining (short) | Model card and design documentation |
| 2(c) Training, testing and validation data: type, provenance, curation, number of data points, scope, how obtained, bias detection | data components and datasets references | DatasetPackage plus trainedOn and testedOn; dataset_datasetSize, dataset_knownBias, dataset_dataCollectionProcess | Dataset cards |
| 2(d) Compute used to train (for example floating point operations), training time | properties | ai_hyperparameter or comment | Model card, compute section |
| 2(e) Known or estimated energy consumption | environmentalConsiderations.energyConsumptions | ai_energyConsumption | Model card, environmental impact |
Annex XI maps to AIBOM fields better than Annex IV, because it lists facts about a model rather than a system. Even so, 2(b) is narrative, and the public training content summary under Article 53(1)(d) follows its own AI Office template. Treat the AIBOM as the structured index of your Annex XI file, linking each narrative field to the card section that explains it.
How to generate the AIBOM from the cards without retyping
The principle: the card's YAML block is the single place a human types the shared facts (licence, base model, datasets, task). Everything else in the AIBOM is derived from the artifact or the build. Here is a working sequence.
Step 1: put the shared facts in the card's YAML block
Use the metadata keys the Hub documents (license, datasets, base_model, pipeline_tag, language). Even for a model that will never be uploaded to a hub, using those keys means the open source generators below can read your card.
---
license: apache-2.0
datasets:
- example/tickets-2025-labelled
base_model: example/example-base-encoder
pipeline_tag: text-classification
language:
- en
---
# Model Card for ticket-classifier
Step 2: for hub hosted models, use an open source generator
cdxgen, under the CycloneDX GitHub organisation, ships a dedicated aibom command. Its AI-BOM guide says it can generate a CycloneDX AI/ML BOM from source, Hugging Face URLs or package URLs, Modelfiles and GGUF artifacts. It maps Hub metadata into standard fields: modelCard.modelParameters.task from pipeline_tag, modelParameters.datasets from dataset references in the model card, considerations.useCases from the task and tags, and lineage from base_model into pedigree.ancestors. Datasets named in the card become reusable data components with dependency edges. Note that the npm package was renamed in version 13, as the cdxgen README explains.
# Install (package renamed to @cdxgen/cdxgen in v13; older releases are @cyclonedx/cdxgen)
npm install -g @cdxgen/cdxgen --ignore-scripts --min-release-age=2
# AIBOM for one hub model, by package URL or URL
aibom pkg:huggingface/<namespace>/<model>@<revision>
aibom https://huggingface.co/<namespace>/<model>
# AIBOM for a local GGUF file or Modelfile
aibom /absolute/path/to/model.gguf
# AIBOM for a whole repository: SDK imports, model files, prompts, MCP configs
cdxgen -t ai --include-formulation -o aibom.json .
For GGUF files, cdxgen's guide describes populating architectureFamily, modelArchitecture, task, datasets, inputs and outputs from the file's metadata, and keeping format specific details as namespaced properties.
The OWASP AIBOM Generator, from the OWASP GenAI Security Project, takes a Hugging Face model ID and produces a CycloneDX 1.6 AIBOM, which its README describes as compatible with the SPDX AI profile. It also scores completeness and suggests improvements, which is a quick way to see which card sections your AIBOM could not fill.
git clone https://github.com/GenAI-Security-Project/aibom-generator.git
cd aibom-generator
pip install -r requirements.txt
# Generate for a hub model, overriding metadata the card does not state
python3 -m src.cli <owner>/<model> \
--name "ticket-classifier" \
--version "2.4.0" \
--manufacturer "Example Corp" \
--output aibom.json
The README also documents an optional inference flag that uses an external AI service to enrich metadata and requires an API key. Leave it off if your card content is confidential.
Step 3: for internal models, lift the YAML block with a short script
Internal models often never touch a public hub. This script reads the card's YAML front matter, hashes the weights file and writes a CycloneDX 1.7 skeleton with the model, its datasets as data components, the base model as an ancestor, and a link back to the card. We ran it on 23 October 2026 and its output validated against the 1.7 schema.
#!/usr/bin/env python3
"""Turn a model card's YAML front matter into a CycloneDX 1.7 AIBOM skeleton.
Usage: card2cdx.py README.md model.safetensors NAME VERSION CARD_URL > aibom.json
"""
import datetime, hashlib, json, pathlib, sys, uuid
import yaml # pip install pyyaml
card_path, weights_path, name, version, card_url = sys.argv[1:6]
text = pathlib.Path(card_path).read_text(encoding="utf-8")
front = yaml.safe_load(text.split("---")[1]) if text.startswith("---") else {}
sha256 = hashlib.sha256(pathlib.Path(weights_path).read_bytes()).hexdigest()
datasets = front.get("datasets") or []
data_refs = [f"data-{d.replace('/', '-')}" for d in datasets]
model = {
"type": "machine-learning-model",
"bom-ref": f"model-{name}",
"name": name,
"version": version,
"hashes": [{"alg": "SHA-256", "content": sha256}],
"externalReferences": [{"type": "model-card", "url": card_url}],
"modelCard": {
"modelParameters": {
"task": front.get("pipeline_tag", "unknown"),
"datasets": [{"ref": r} for r in data_refs],
}
},
}
if front.get("license"):
# Hub licence ids are lower case; map the ones you use to SPDX ids.
spdx = {"apache-2.0": "Apache-2.0", "mit": "MIT"}.get(front["license"])
model["licenses"] = [{"license": {"id": spdx}} if spdx else {"license": {"name": front["license"]}}]
if front.get("base_model"):
bases = front["base_model"] if isinstance(front["base_model"], list) else [front["base_model"]]
model["pedigree"] = {"ancestors": [{"type": "machine-learning-model", "name": b} for b in bases]}
data = [{"type": "data", "bom-ref": r, "name": d, "data": [{"type": "dataset", "name": d}]}
for r, d in zip(data_refs, datasets)]
bom = {
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"serialNumber": f"urn:uuid:{uuid.uuid4()}",
"version": 1,
"metadata": {"timestamp": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")},
"components": [model] + data,
"dependencies": [{"ref": model["bom-ref"], "dependsOn": data_refs}] + [{"ref": r} for r in data_refs],
}
json.dump(bom, sys.stdout, indent=2)
The script deliberately stops at the shared facts. It does not try to parse the card's prose into considerations or performanceMetrics. If you want those fields filled, add them to the YAML block as structured keys (the Hub's model-index block is one convention for evaluation results) and extend the script, rather than scraping Markdown headings. Map licence identifiers carefully: Hub licence keys are lower case, while CycloneDX license.id must be a valid SPDX licence identifier, which is why the script falls back to license.name for anything it does not recognise.
Step 4: validate before you publish
Validate every generated AIBOM against the schema version it declares. The CycloneDX CLI's validate command accepts input versions up to v1_7 and can return a non zero exit code to break a build. cdxgen ships cdx-validate for structural and posture checks.
# CycloneDX CLI: validate a 1.7 document and fail the build on errors
cyclonedx validate --input-file aibom.json --input-version v1_7 --fail-on-errors
# cdxgen's validator
cdx-validate -i aibom.json
For SPDX 3 output, validate JSON structure against the published 3.0.1 JSON schema and use the SPDX project's SHACL based tooling for profile conformance.
Step 5: regenerate in CI whenever the card or the weights change
This GitHub Actions workflow regenerates the AIBOM whenever the card or the weights change, validates it, and keeps it as a build artifact. It assumes the script above is committed at tools/card2cdx.py and the weights are tracked with Git LFS.
name: aibom
on:
push:
paths:
- "models/ticket-classifier/**"
jobs:
aibom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: true
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install pyyaml jsonschema referencing
- name: Generate AIBOM from the card
run: |
python tools/card2cdx.py \
models/ticket-classifier/README.md \
models/ticket-classifier/model.safetensors \
ticket-classifier "${GITHUB_SHA::7}" \
"https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA}/models/ticket-classifier/README.md" \
> aibom.json
- name: Validate against CycloneDX 1.7
run: |
base=https://raw.githubusercontent.com/CycloneDX/specification/master/schema
mkdir -p schema
for f in bom-1.7.schema.json spdx.schema.json jsf-0.82.schema.json cryptography-defs.schema.json; do
curl -fsSL "$base/$f" -o "schema/$f"
done
python tools/validate_cdx.py schema aibom.json
- uses: actions/upload-artifact@v4
with:
name: aibom
path: aibom.json
The validate_cdx.py helper loads the four schema files into a registry so the cross file references resolve, then validates the document and exits non zero on any error. Swap that step for the CycloneDX CLI if you already use it.
#!/usr/bin/env python3
"""Usage: validate_cdx.py SCHEMA_DIR BOM.json (pip install jsonschema referencing)"""
import json, pathlib, sys
from jsonschema import Draft7Validator
from referencing import Registry, Resource
from referencing.jsonschema import DRAFT7
schema_dir, bom_path = pathlib.Path(sys.argv[1]), sys.argv[2]
resources = []
for p in schema_dir.glob("*.json"):
r = Resource.from_contents(json.loads(p.read_text()), default_specification=DRAFT7)
resources.append((p.name, r))
if "$id" in r.contents:
resources.append((r.contents["$id"], r))
schema = json.loads((schema_dir / "bom-1.7.schema.json").read_text())
errors = list(Draft7Validator(schema, registry=Registry().with_resources(resources))
.iter_errors(json.load(open(bom_path))))
for e in errors:
print(list(e.absolute_path), e.message)
sys.exit(1 if errors else 0)
``` Because the AIBOM is rebuilt from the card on every change, the two cannot drift apart silently: a licence change in the card shows up as a diff in the AIBOM, and a new weights file changes the hash.
### Step 6: sign it and ship it with the model
An AIBOM nobody can verify is a claim, not evidence. Sign the AIBOM alongside the model artifact using the same signing and attestation flow you use for SBOMs, and publish both together, so a consumer can confirm the AIBOM describes the exact file they downloaded.
## Where Safeguard fits
Safeguard's **AI-BOM discovery is in early access**. It inventories AI assets across code (SDK imports), cloud AI services (SageMaker, Bedrock and Vertex), SaaS usage (shadow AI) and vector databases, and produces an ML-BOM in CycloneDX and the SPDX AI profile. That is the inventory half of this post: which models and AI services you actually use, where. It does not write model cards or dataset cards for you, and Safeguard does not generate dataset or data BOMs; the narrative and the dataset documentation remain your team's work.
Several generally available capabilities sit around it. **SBOM generation and analysis** produces SPDX (JSON, XML, RDF) and CycloneDX (JSON, XML), so the application SBOM your AIBOM belongs in comes from the same place. **License compliance** parses SPDX expressions and applies policy, which matters once model and dataset licences are machine readable. **Attestation and signing** covers SLSA, Sigstore keyless signing with Fulcio and Rekor, in-toto and X.509, which is step 6. **Policies and gates** block, warn or require approval at build, CI and release checkpoints. **Third party risk management** lets you request SBOMs from suppliers, including the vendors whose models you use. **Model scanning** for LLMs, SLMs, skills and agents is also generally available.
The honest limit: the questions only a card can answer, such as intended use, evaluation method and limitations, are answered by people. No tool, including ours, should pretend to write them.
## Common mistakes
**Treating the model card as the AIBOM.** A card with a filled YAML block has no hash, no dependency graph and no resolvable dataset identifiers. It cannot tell an auditor whether the deployed file is the evaluated file.
**Treating the AIBOM as the model card.** Pasting whole paragraphs into `technicalLimitations` makes the AIBOM unreadable, and the card's audience, who will not open a JSON file, gets nothing.
**Retyping shared facts in two places.** Licence and base model typed separately will drift. Generate the AIBOM fields from the card's YAML.
**Hub licence keys in SPDX licence fields.** Keys such as `apache-2.0` are not SPDX identifiers. CycloneDX `license.id` and SPDX expressions need `Apache-2.0`. Map them, or use a licence name.
**Leaving datasets as names.** Make each dataset a CycloneDX `data` component referenced by `bom-ref`, or an SPDX `DatasetPackage` linked with `trainedOn` or `testedOn`.
**Folding training and test data together silently.** CycloneDX's `datasets` list holds both. If the split matters, as under Annex IV point 2(g), say which is which in the description or use SPDX's separate relationship types.
**Skipping the SPDX licence relationships.** A document can pass JSON Schema and still fail the profiles' rule of one declared and one concluded licence per package.
**Pinning nothing.** An AIBOM that names a hub model without a revision describes whatever the hub serves today. Use revisioned package URLs.
## FAQ
### What is the difference between a model card and an AIBOM?
A model card is a human readable document explaining a model's intended use, evaluation, limitations and ethical considerations. An AIBOM is a machine readable bill of materials in CycloneDX or SPDX 3 that lists the model artifact, its hash, datasets, parent models, dependencies and licences. The card explains; the AIBOM identifies and links.
### Is a model card machine readable?
Only partly. Model cards on model hubs are Markdown files with a YAML metadata block at the top. Tools can read the YAML (licence, datasets, base model, task). The body is prose for people.
### Does CycloneDX include a model card?
Yes. Since CycloneDX 1.5, a component of type `machine-learning-model` can carry a `modelCard` object with `modelParameters`, `quantitativeAnalysis` and `considerations`. It holds structured summaries; the full card can be linked with an external reference of type `model-card`.
### How does SPDX 3 describe AI models and datasets?
SPDX 3.0 adds an AI profile with an `AIPackage` class and a Dataset profile with a `DatasetPackage` class, both subclasses of the software package. Models link to datasets with `trainedOn` and `testedOn` relationships, and each package must have declared and concluded licence relationships.
### What is the difference between a dataset card and a datasheet for datasets?
The datasheet is the 2018 research proposal by Gebru and colleagues for documenting a dataset's motivation, composition, collection and recommended uses. A dataset card is the practical form used on dataset hubs, a README with YAML metadata whose sections follow the same ideas.
### Does the EU AI Act require an AIBOM?
Not by that name. Annex IV (high risk systems) and Annex XI (general purpose AI models) list documentation contents. Software versions, components, pre trained systems and data provenance are inventory an AIBOM carries well; design rationale and evaluation method belong in cards and the technical file.
### Can I generate an AIBOM from a Hugging Face model card?
Yes. cdxgen's `aibom` command and the OWASP AIBOM Generator both read Hub metadata and produce CycloneDX AIBOMs. They fill what the card states and leave the rest empty, so a thin card produces a thin AIBOM.
### Who should write the model card, and who should produce the AIBOM?
The team that trained or fine tuned the model writes the card, because only they know the intended use and evaluation details. The AIBOM should be generated by the build or an inventory tool from the artifact and the card's metadata, then reviewed by the same team.
### Where does a CycloneDX ML-BOM put hyperparameters?
There is no dedicated hyperparameter field in the CycloneDX 1.7 `modelParameters` object, despite its description mentioning hyperparameters; it holds approach, task, architecture, datasets, inputs and outputs. Use `properties` for hyperparameter values. SPDX 3 has a dedicated `ai_hyperparameter` property.
## Fix it without waiting for upstream
An AIBOM tells you which model, runtime and libraries an AI system contains, but it does not patch any of them; when a vulnerability lands in the inference runtime or a Python dependency the model needs, someone still has to ship a fixed build. The fit with model and dataset documentation is indirect, so the steps below apply to the open source packages and container images that carry your models, not to the model weights or the cards themselves.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
### 1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
### 2. Gold Open Source: the safe version in seconds, free
[gold.safeguard.sh](https://gold.safeguard.sh) is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The `safeguard-sh/gold-scan-action` GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
### 3. Gold Registry: start from components that are already fixed
[registry.safeguard.sh](https://registry.safeguard.sh) provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
## See how Safeguard would help
These demos are general Safeguard flows, not AIBOM specific features.
The first is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, edit package.json, run npm install and npm test with your approval, and push nothing. The same approval driven loop works for adding the card to AIBOM step to a model repository's CI, with you reviewing each edit.
<iframe src="/demos/safeguard-cli-in-action/embed" title="Interactive demo: Safeguard CLI in action" width="100%" height="560" loading="lazy" allowFullScreen></iframe>
Click through it at your own pace, or [open it full screen](/demos/safeguard-cli-in-action).
This demo sets up the runner on your own machine, approves it with its device code, then scans from the terminal. For model repositories with large weights or confidential cards, running scans locally keeps those files on hardware you control.
<iframe src="/demos/local-runner-cli/embed" title="Interactive demo: Local runner CLI" width="100%" height="560" loading="lazy" allowFullScreen></iframe>
Click through it at your own pace, or [open it full screen](/demos/local-runner-cli).
This demo connects Claude to the Safeguard MCP server with OAuth and shows how you choose which tools Claude can use. Depending on which tools you enable, you can then ask about your projects and components in plain language, which is useful when an AI library or runtime named in an AIBOM needs to be traced across products.
<iframe src="/demos/claude-with-safeguard/embed" title="Interactive demo: Claude with Safeguard" width="100%" height="560" loading="lazy" allowFullScreen></iframe>
Click through it at your own pace, or [open it full screen](/demos/claude-with-safeguard).
To try it on your own repositories, [download Safeguard](https://safeguard.sh/download) or read the [CLI documentation](https://docs.safeguard.sh/docs/cli).
## Quick check
<details>
<summary>An auditor asks whether the model file running in production is the one your evaluation report describes. Which document answers that?</summary>
The AIBOM. Only a bill of materials carries a cryptographic hash of the artifact (CycloneDX `hashes`, SPDX `verifiedUsing`) that you can compare with the deployed file. The model card describes the evaluation but cannot prove which file it applied to.
</details>
<details>
<summary>Annex IV point 2(d) of the EU AI Act asks for data requirements "in terms of datasheets". Is an SPDX DatasetPackage enough on its own?</summary>
No. The DatasetPackage carries identity, size, type, provenance links, sensitivity flags, known bias and licences, which covers the inventory part. How the data was obtained and selected, labelling procedures and cleaning methods need the narrative of a dataset card or datasheet, with the AIBOM linking to it.
</details>
## Sources
- [CycloneDX: Machine Learning Bill of Materials (ML-BOM) capability page](https://cyclonedx.org/capabilities/mlbom/)
- [CycloneDX specification: bom-1.7.schema.json](https://github.com/CycloneDX/specification/blob/master/schema/bom-1.7.schema.json)
- [CycloneDX specification: bom-1.6.schema.json](https://github.com/CycloneDX/specification/blob/master/schema/bom-1.6.schema.json)
- [CycloneDX specification: bom-1.5.schema.json and bom-1.4.schema.json (modelCard presence check)](https://github.com/CycloneDX/specification/tree/master/schema)
- [CycloneDX CLI README (validate command)](https://github.com/CycloneDX/cyclonedx-cli)
- [cdxgen README](https://github.com/CycloneDX/cdxgen)
- [cdxgen AI-BOM guide](https://github.com/CycloneDX/cdxgen/blob/master/docs/AI_BOM.md)
- [SPDX 3.0.1: AI profile](https://spdx.github.io/spdx-spec/v3.0.1/model/AI/AI/)
- [SPDX 3.0.1: AIPackage class](https://spdx.github.io/spdx-spec/v3.0.1/model/AI/Classes/AIPackage/)
- [SPDX 3.0.1: Dataset profile](https://spdx.github.io/spdx-spec/v3.0.1/model/Dataset/Dataset/)
- [SPDX 3.0.1: DatasetPackage class](https://spdx.github.io/spdx-spec/v3.0.1/model/Dataset/Classes/DatasetPackage/)
- [SPDX 3.0.1: RelationshipType vocabulary](https://spdx.github.io/spdx-spec/v3.0.1/model/Core/Vocabularies/RelationshipType/)
- [SPDX 3.0.1 JSON schema](https://spdx.org/schema/3.0.1/spdx-json-schema.json)
- [OWASP GenAI Security Project: AI Bill of Materials initiative](https://genai.owasp.org/owasp-aibom/)
- [OWASP AIBOM Generator repository](https://github.com/GenAI-Security-Project/aibom-generator)
- [European Commission AI Act Service Desk: Article 11, Technical documentation](https://ai-act-service-desk.ec.europa.eu/en/ai-act/article-11)
- [European Commission AI Act Service Desk: Annex IV](https://ai-act-service-desk.ec.europa.eu/en/ai-act/annex-4)
- [European Commission AI Act Service Desk: Article 53](https://ai-act-service-desk.ec.europa.eu/en/ai-act/article-53)
- [European Commission AI Act Service Desk: Annex XI](https://ai-act-service-desk.ec.europa.eu/en/ai-act/annex-11)
- [European Commission AI Act Service Desk: Article 113, Entry into force and application](https://ai-act-service-desk.ec.europa.eu/en/ai-act/article-113)
- [Mitchell et al., "Model Cards for Model Reporting", arXiv:1810.03993 (research paper)](https://arxiv.org/abs/1810.03993)
- [Gebru et al., "Datasheets for Datasets", arXiv:1803.09010 (research paper)](https://arxiv.org/abs/1803.09010)
- [Hugging Face Hub documentation: Model cards (hosting platform convention)](https://huggingface.co/docs/hub/model-cards)
- [Hugging Face Hub documentation: Dataset cards (hosting platform convention)](https://huggingface.co/docs/hub/datasets-cards)
- [huggingface_hub model card template](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/templates/modelcard_template.md)
- [huggingface_hub dataset card template](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/templates/datasetcard_template.md)
Last reviewed: 23 October 2026. Specification versions and EU AI Act application dates change; check the linked sources for the latest status.