Skip to content
All posts
Seriesaibom-library

AIBOM Identity, Provenance and Lineage

October 29, 2026 · PlayCISO
TL;DR

The identity section of an AIBOM says exactly which model runs: a name, your version, a package URL pinned to a revision, the supplier and a hash of the files. The lineage section says what it was built from: pedigree.ancestors in CycloneDX, a descendantOf relationship in SPDX 3.0, and base_model with base_model_relation on a Hugging Face card. Record every layer the supplier documents, because licence limits, backdoors and broken tokenizers travel down the family tree.

Put it into practice
See the lineage fields in every format
The AIBOM Format Field Map (Pro) lines up base model, derivation type, version, supplier and hash across CycloneDX, SPDX 3.0, Croissant, the EU forms and Hugging Face cards.
Open the Field Map

The identity part of an AIBOM says exactly which model you run. The lineage part says what that model was built from. Give every model a name, a version, a package URL pinned to a revision, a supplier and a hash, list each base model as its own component, and link every derived model to its parents: pedigree.ancestors in CycloneDX, descendantOf in SPDX 3.0, base_model on a Hugging Face card. This page gives the field for each kind of derivation and shows them on the fictional Northwind example.

Who this is for: AppSec and AI-security engineers who generate the AIBOM in CI, and SOC analysts who must answer “were we running it?” when a model, or the model under it, turns out to be bad.

What the identity and lineage section must answer

  • Which model is this, exactly? Not a family name, but the files that were deployed.
  • Who supplied it? For your own model and for every model under it.
  • Can we prove it? A hash, and a signature that says who produced those bytes.
  • What was it built from? Base models, adapters, merges and quantisations, as far down as the supplier documents.

Our AIBOM parameters checklist lists these as “name, version, source, relationship”. This page is the field-level version.

Identity fields across the formats

Field names are from the CycloneDX 1.7 JSON schema, SPDX 3.0.1 and the Hugging Face model card spec. The last column is the fictional Northwind entry.

FactCycloneDX 1.7SPDX 3.0.1Hugging Face cardNorthwind (fictional)
Name and namespacegroup + namenameRepository ID (namespace/name)northwind / triage-assistant
Your versionversionsoftware_packageVersion (required on an AIPackage)Revision (Git commit hash)2.3.0
Pinned identifierpurl; also cpe, omniborId, swhidsoftware_packageUrl; externalIdentifierRepository ID + revisionBase: pkg:huggingface/mistralai/Mistral-7B-Instruct-v0.3@c170c708…
Who supplied itsupplier, manufacturer, authors, publishersuppliedBy (required on an AIPackage), originatedByRepository ownerNorthwind Health; base: Mistral AI
When it was releasedNo component field (metadata.timestamp is when the BOM was made; releaseNotes.timestamp if you ship release notes)releaseTime (required on an AIPackage)Commit dates in the repository2026-02-16
Which byteshashes (SHA-256 and others)verifiedUsing (Hash)No metadata fieldOne SHA-256 for the weights file (placeholder in the example)
Where to get itexternalReferences type distributionsoftware_downloadLocation (required on an AIPackage)The repository URLmodel.safetensors on an internal host

Here is the model and its base as they appear in Northwind’s CycloneDX file:

[
  {
    "type": "machine-learning-model",
    "bom-ref": "model:northwind/triage-assistant@2.3.0",
    "supplier": { "name": "Northwind Health", "url": ["https://northwind-health.example"] },
    "group": "northwind",
    "name": "triage-assistant",
    "version": "2.3.0",
    "hashes": [
      {
        "alg": "SHA-256",
        "content": "3bad18cc9805cb1211d9929cbef60f590e64c4bc71bf88fb5c22ba6da68754fa"
      }
    ],
    "pedigree": {
      "ancestors": [
        {
          "type": "machine-learning-model",
          "supplier": { "name": "Mistral AI" },
          "group": "mistralai",
          "name": "Mistral-7B-Instruct-v0.3",
          "purl": "pkg:huggingface/mistralai/Mistral-7B-Instruct-v0.3@c170c708c41dac9275d15a8fff4eca08d52bab71",
          "licenses": [{ "license": { "id": "Apache-2.0" } }]
        }
      ],
      "notes": "Fine-tuned from mistralai/Mistral-7B-Instruct-v0.3 with LoRA adapters merged into the base weights before release."
    }
  },
  {
    "type": "machine-learning-model",
    "bom-ref": "model:mistralai/Mistral-7B-Instruct-v0.3",
    "supplier": { "name": "Mistral AI" },
    "group": "mistralai",
    "name": "Mistral-7B-Instruct-v0.3",
    "purl": "pkg:huggingface/mistralai/Mistral-7B-Instruct-v0.3@c170c708c41dac9275d15a8fff4eca08d52bab71",
    "licenses": [{ "license": { "id": "Apache-2.0" } }]
  }
]

Excerpt, 38 lines: the fine-tuned model and its base model from the components array. Keys not shown are left out; every value shown is exactly as in the full file (519 lines pretty-printed), which is in the Pro AIBOM Template Library.

Four identity rules that trip people up

1. The name is not the version

mistralai/Mistral-7B-Instruct-v0.3 sounds versioned. It is not. “v0.3” is part of the repository name, and the files behind that name kept changing after release. The repository was created on 22 May 2024 and, on 29 October 2026, had 34 commits on its main branch. They include a chat-template update on 20 June 2024, a tokenizer alignment on 17 July 2024, tool-calling support in the chat template on 2 August 2024 and README edits as late as 3 December 2025. Two teams that both “use Mistral-7B-Instruct-v0.3” can be running different chat templates.

The fix is in the package URL. For the huggingface purl type, the version is the model revision’s Git commit hash. Northwind’s file pins c170c708c41dac9275d15a8fff4eca08d52bab71, the head of main on 29 October 2026. SPDX puts the same hash in software_packageVersion on the base model’s AIPackage.

2. Hash what you load, all of it

A model is a directory, not a file. The Mistral base repository holds three sharded safetensors files, a consolidated safetensors file, tokenizer files and configuration. The tokenizer and the chat template change behaviour without touching the weights. CycloneDX hashes describe one component, so either list each file as a nested file component with its own hashes, or rely on a signed manifest that digests every file, which is what OpenSSF model signing produces. Northwind ships one merged model.safetensors and records one SHA-256 for it (a placeholder in our example) plus a signature.

3. Your version must move when behaviour can

Bump the model version for new weights, a new tokenizer, a new chat template or new generation defaults. If two builds with different behaviour share a version, the AIBOM cannot tell an incident responder which one answered.

4. Name the supplier of every layer

CycloneDX separates the supplier (“may often be the manufacturer, but may also be a distributor or repackager”) from the manufacturer (the organisation that created it) and authors. Northwind supplies the fine-tune; Mistral AI supplies the base. Download mirrors are suppliers too: if you pulled weights from a mirror, say so.

Lineage: one family tree, seven kinds of link

Every derived model needs a link to its parents. The right field depends on how it was derived.

DerivationWhat it isCycloneDX 1.7SPDX 3.0.1Hugging Face cardWhat to hash
Full fine-tuneAll weights trained further from a base model.pedigree.ancestors: [base]; method in pedigree.notesdescendantOf → basebase_model; relation finetuneThe new weights
Adapter shipped separately (LoRA, PEFT)Small adapter files loaded on top of an unchanged base at run time.Adapter component with pedigree.ancestors: [base], plus a dependencies edge to the basedescendantOf and dependsOn → basebase_model; relation adapterThe adapter files and the exact base revision it was trained on
Adapter merged before release (Northwind)The LoRA weights are folded into the base weights; one set of files ships.pedigree.ancestors: [base]; pedigree.notes says “merged”. Northwind also lists the base as its own component with a dependency edge, so tools that only read components still see itdescendantOf → basebase_model; we set finetune: a merged adapter is no longer an adapterThe merged files
Quantisation (GPTQ, AWQ, GGUF and others)The same model at lower numeric precision. Behaviour can shift.pedigree.ancestors: [full-precision model]; method and bit width in notes or propertiesdescendantOf → full-precision modelbase_model; relation quantizedThe quantised files: they differ from the original
Merge of several modelsWeights combined from two or more parents.pedigree.ancestors: one entry per parentdescendantOf with every parent in tobase_model as a list; relation mergeThe merged files
Relationship unknownLooks like a known model, but you cannot show it was derived from it.pedigree.variantshasVariantNo fieldThe files you have
DistillationTrained on another model’s outputs; no weights inherited.No dedicated field: pedigree.notes or formulationNo dedicated relationship: ai_informationAboutTrainingNo dedicated fieldThe student’s weights

CycloneDX defines ancestors as the components a component “is derived from”, descendants as the opposite, and variants as relations “where the relationship between the components is not known”. SPDX’s descendantOf reads “the from Element is a descendant of each to Element”. On the Hugging Face Hub, the relation values are adapter, merge, quantized and finetune.

Record the whole chain the supplier documents

Mistral-7B-Instruct-v0.3 is itself a derivative. Its model card sets base_model: mistralai/Mistral-7B-v0.3 (metadata added on 19 August 2024) and describes the model as “an instruct fine-tuned version of the Mistral-7B-v0.3”. So Northwind’s chain is three models deep: Mistral-7B-v0.3 → Mistral-7B-Instruct-v0.3 → northwind/triage-assistant 2.3.0. The canonical file records the immediate parent. A nested pedigree adds the grandparent, pinned to its own revision:

{
  "ancestors": [
    {
      "type": "machine-learning-model",
      "supplier": { "name": "Mistral AI" },
      "group": "mistralai",
      "name": "Mistral-7B-Instruct-v0.3",
      "purl": "pkg:huggingface/mistralai/Mistral-7B-Instruct-v0.3@c170c708c41dac9275d15a8fff4eca08d52bab71",
      "licenses": [{ "license": { "id": "Apache-2.0" } }],
      "pedigree": {
        "ancestors": [
          {
            "type": "machine-learning-model",
            "supplier": { "name": "Mistral AI" },
            "group": "mistralai",
            "name": "Mistral-7B-v0.3",
            "purl": "pkg:huggingface/mistralai/Mistral-7B-v0.3@caa1feb0e54d415e2df31207e5f4e273e33509b1",
            "licenses": [{ "license": { "id": "Apache-2.0" } }]
          }
        ],
        "notes": "Instruction-tuned by Mistral AI from Mistral-7B-v0.3, as declared by base_model on the supplier’s model card."
      }
    }
  ],
  "notes": "Fine-tuned from mistralai/Mistral-7B-Instruct-v0.3 with LoRA adapters merged into the base weights before release."
}

A pedigree for northwind/triage-assistant that records the grandparent. We wrote this for the post; the revision and licence of Mistral-7B-v0.3 are real (Hugging Face API, 29 October 2026). It validates against the CycloneDX 1.7 schema inside the full Northwind BOM.

The same lineage in SPDX and on a model card

[
  {
    "type": "ai_AIPackage",
    "spdxId": "https://northwind-health.example/spdx/triage-assistant-2.3.0#base-model",
    "name": "mistralai/Mistral-7B-Instruct-v0.3",
    "software_packageVersion": "c170c708c41dac9275d15a8fff4eca08d52bab71",
    "software_packageUrl": "pkg:huggingface/mistralai/Mistral-7B-Instruct-v0.3@c170c708c41dac9275d15a8fff4eca08d52bab71",
    "releaseTime": "2024-05-22T09:57:04Z",
    "suppliedBy": "https://northwind-health.example/spdx/triage-assistant-2.3.0#org-mistral-ai"
  },
  {
    "type": "Relationship",
    "spdxId": "https://northwind-health.example/spdx/triage-assistant-2.3.0#rel-3",
    "creationInfo": "_:creationinfo",
    "from": "https://northwind-health.example/spdx/triage-assistant-2.3.0#model",
    "relationshipType": "descendantOf",
    "to": ["https://northwind-health.example/spdx/triage-assistant-2.3.0#base-model"]
  }
]

Excerpt, 19 lines: the base model’s AIPackage and the descendantOf relationship from Northwind’s SPDX 3.0.1 file. Keys not shown are left out; every value shown is exactly as in the full file (608 lines pretty-printed), which is in the Pro AIBOM Template Library.

If Northwind wrote an internal Hugging Face-style card for its model, the YAML header would carry the same facts:

---
license: other
license_name: northwind-proprietary
license_link: LICENSE
base_model: mistralai/Mistral-7B-Instruct-v0.3
base_model_relation: finetune   # LoRA merged into the weights before release
pipeline_tag: text-generation
datasets:
- northwind/support-tickets-2025
---

Written for this post. license: other with license_name and license_link is how the Hub spec handles a licence that is not on its list. The card is internal and never published.

What the SOC does with lineage

When an advisory, a licence change or a backdoor report names a model, the question is “which of our systems derive from it?” With lineage in every AIBOM, the answer is a search:

  1. Match the named model’s purl, ignoring the version, against every component and every pedigree.ancestors entry, at any depth.
  2. Compare revisions. A fix published after the revision you pinned does not help you until you rebuild.
  3. Read the derivation type. It decides the fix. A separately shipped adapter loads its base at run time, so you can swap the base, then retest the adapter on it. A fine-tuned, merged or quantised model carries the base weights inside it: replacing the base means rebuilding the derivative.

Lineage also carries licences. Northwind’s merged weights contain the Apache-2.0 base weights, so the base licence sits on the ancestor where a licence check will find it. The Model License Checker reads model licences; the AIBOM Diff shows when an ancestor changes between releases.

Where regulators ask for lineage

  • EU AI Act Annex IV, point 2(a): the development methods, “including, where relevant, recourse to pre-trained systems or tools provided by third parties and how those were used, integrated or modified by the provider”. See our Annex IV walkthrough.
  • GPAI Model Documentation Form, “Model dependencies”: for a modified or fine-tuned general-purpose model, the names (and versions) of the models it was built from. See the form explainer.

Identity and lineage checklist

  • Every model, including every base model, is its own component with a name, your version and a supplier.
  • Third-party models carry a purl pinned to a revision hash, not just a repository name.
  • Every file you load is hashed, or covered by a signed manifest.
  • Every derived model links to each parent, with the derivation type stated.
  • The chain goes as deep as the suppliers document it.
  • The version moves whenever weights, tokenizer, chat template or generation defaults change.
  • The hash is backed by a signature and a provenance attestation, linked from the AIBOM.

The rest of the AIBOM

Identity and lineage are one section of four. The data section covers the datasets the model was trained and tested on. The security and runtime section covers signing, serialization formats and what the model can reach. The evaluation and intended-use section covers what the model is fit to do. For the full CycloneDX file, read CycloneDX ML-BOM: fields and a worked example and SPDX 3.0 AI and Dataset profiles. Every guide by role is on the AIBOM Library hub.

Fictional example. Northwind Health, Triage Assistant and its datasets, services, scores and URLs are invented for illustration; the base model and open-source libraries are real.

Frequently asked questions

How do I record a fine-tuned model’s base model in an AIBOM?

In CycloneDX, put the base model in the fine-tune’s pedigree.ancestors and also list it as its own machine-learning-model component. In SPDX 3.0, add a descendantOf relationship from the fine-tune’s AIPackage to the base model’s AIPackage. On a Hugging Face model card, set base_model to the base repository ID; the Hub infers the relation (adapter, merge, quantized or finetune), and you can set base_model_relation yourself.

What is the version of a Hugging Face model?

The Git commit hash of the repository revision. The package URL type for Hugging Face models uses it as the version: pkg:huggingface/namespace/name@commit-hash. A suffix such as v0.3 in a repository name is part of the name, not a version, and the files behind that name can change after release.

Does a LoRA adapter need its own AIBOM entry?

If you ship the adapter as separate files, yes: it is a model component that needs its base at run time, so record the base as its ancestor and as a dependency, and hash both. If you merge the adapter into the base weights before release, the merged model is one component whose ancestor is the base, and you hash the merged files.

How do I record a quantised or merged model?

A quantised model is a derivative of the full-precision model: list that model as its ancestor and record the method and bit width in pedigree notes or a property, because neither CycloneDX nor SPDX has a dedicated field for them. A merge has several parents: one ancestor each in CycloneDX, a descendantOf relationship to each in SPDX, and a list in base_model on a Hugging Face card.

Why does model lineage matter for security?

Because problems travel down the family tree. A licence restriction, a poisoned or backdoored base, or a broken tokenizer in a base model affects every fine-tune, adapter, quantisation and merge built on it. With lineage recorded, “which of our systems derive from model X?” becomes a query over your AIBOMs.

Is a model hash enough to prove provenance?

No. A hash proves which bytes you have, not who produced them or how. Pair it with a signature over the model files, for example OpenSSF model signing with Sigstore, and a build provenance attestation such as SLSA provenance, which names the inputs. The AIBOM links to both.

Sources

Checked on 29 October 2026. PlayCISO is not affiliated with any standards body, vendor or project named here. This is general information, not legal advice.

See the lineage fields in every format
The AIBOM Format Field Map (Pro) lines up base model, derivation type, version, supplier and hash across CycloneDX, SPDX 3.0, Croissant, the EU forms and Hugging Face cards.
Open the Field Map

Ready to practise the decisions these articles describe?

Run your first War Room free →

One run free with a free account · more runs with Pro

🎉 New here? Use code WELCOME10 for 10% off any plan at checkout