A model signature lets you check that the files on your disk are the ones a known publisher signed, before any code loads the weights.[1] The check is only as strong as the signer identity you compare it against, and it covers only the signed files. Each step below therefore pairs a command with the decision it supports. The guide uses model_signing, the command-line tool of the model-signing package from Sigstore's model-transparency project.[1, 2] Version 1.1.1 was the current release on the Python Package Index (PyPI) on 20 October 2026.[2] Our brief on the 1.0 release gives the background.

When to use this guide

Use it when a signed model arrives and you are about to serve it, fine-tune it or hand it to another system. The AI/ML working group of the Open Source Security Foundation (OpenSSF) announced the 1.0 release in April 2025. The group says signatures should be checked each time a model is used, including when it is selected for deployment and when it becomes input to another model.[8]

What you need before you start

  • The model directory, exactly as you will load it and made of regular files. The tool stops with an error at a symbolic link unless you allow links.[5]
  • The signature bundle distributed with the model, which the tool names model.sig by default.[1, 3]
  • The expected signer, from a channel you already trust, such as the publisher's documentation. Never copy it from the bundle: the bundle names whoever signed, who may not be the publisher.
    • For a Sigstore signature: the signer's OpenID Connect (OIDC) identity and its issuer, the identity provider. The identity is an email address, or a workload identity such as a continuous integration (CI) workflow for automated signing. Issuers include https://accounts.google.com and the GitHub Actions issuer, https://token.actions.githubusercontent.com.[1, 3]
    • For a key signature: the publisher's public key.
    • For a certificate signature: the publisher's certificate chain.
  • Python 3.9 or later, which the 1.1.1 release requires.[2]

Step 1: Install a pinned release

Install one exact version, then check the version the tool reports.

pip install model-signing==1.1.1
model_signing --version

Version 1.1.1 spells several flags with underscores, such as --identity_provider.[3] An unreleased change switches to hyphens and keeps accepting the underscore forms.[7] Commands written for a later release may therefore fail on 1.1.1. Follow the README at the tag of your release.[1]

Step 2: Verify against the signer you expect

With Sigstore, the signer uses a short-lived certificate for its OIDC identity. The signing event is recorded in a public, append-only transparency log.[1, 9] The identity and issuer are required arguments, and verification fails if they do not match the signature.[3]

model_signing verify path/to/model \
  --signature model.sig \
  --identity "$EXPECTED_IDENTITY" \
  --identity_provider "$EXPECTED_ISSUER"

For a key signature, pass the publisher's public key, which is your only link to the publisher.[3]

model_signing verify key path/to/model \
  --signature model.sig \
  --public_key publisher.pub

For a certificate signature, you must identify the signer yourself, because the command checks the chain but takes no expected signer name.[3] Without --certificate_chain, it falls back to a default set of root certificates.[4] Version 1.1.1 accepts some certificates whose extended key usage field does not permit code signing, such as certificates issued for web servers. The fix has not been released.[7] Pass the publisher's own chain, and identify the signer by confirming the signing certificate's SHA-256 fingerprint with the publisher; --log_fingerprints logs it.[3]

model_signing verify certificate path/to/model \
  --signature model.sig \
  --certificate_chain publisher-chain.pem \
  --log_fingerprints

Step 3: Read what the result covers

Read the output: the command prints Verification succeeded, or Verification failed with error: followed by the reason. On failure it exits with status 1.[3] It hashes the directory and fails if a signed file has changed or is missing, or if an extra file is present. The error names the files.[4]

A pass says nothing about skipped paths, which include Git-related files by default.[1] Since version 1.1.0, a signature also records the paths the publisher excluded at signing, and verification skips them automatically.[7] Two flags add to these: --ignore-paths skips paths you name, and --ignore_unsigned_files lets extra files pass.[3, 7] Use them only for files your loader never reads.

Leave --allow_symlinks off. With it on, version 1.1.1 silently leaves every file under a symbolic link to a directory unsigned and unchecked. The changelog lists this flaw as fixed only in unreleased code.[7]

To see what the signature covers, decode its signed statement with the jq tool:[9]

jq -r .dsseEnvelope.payload model.sig | base64 -d | jq .

In the output, predicate.resources lists each covered file with its hash algorithm and digest (the hash value). The predicate.serialization field records the hashing settings, including any paths excluded at signing.[6] A predicateType of https://model_signing/Digests/v0.1 marks a pre-1.0 signature. The tool can verify such a signature but not create one, replicating version 0.2's experimental behavior "bug for bug," as the changelog puts it.[6, 7]

Step 4: Check the transparency log entry

This step applies only to Sigstore signatures, which are recorded in Rekor, Sigstore's append-only transparency log.[1, 11] The verify command has already checked the bundle's proof that the entry is in the log.[1, 9] The bundle also holds the entry's log index and its integrated time, the time the log recorded the entry. A signed timestamp in the bundle shows that signing happened while the short-lived certificate was valid. Verification can therefore succeed after the certificate expires.[9]

jq '.verificationMaterial.tlogEntries[] | {logIndex, integratedTime}' model.sig
rekor-cli get --rekor_server https://rekor.sigstore.dev --log-index <log-index>

The second command fetches the entry with the Rekor command-line client.[10] The server it queries hosts Rekor's original log, which is still the default for Sigstore's public instance. The version 2 logs that ecosystems can opt into have other addresses.[11, 12]

Step 5: Record the result

Keep enough for an auditor to repeat the check.

Using the digests in an AI bill of materials

In May 2026, cybersecurity agencies of the Group of Seven (G7) countries published minimum elements for a software bill of materials (SBOM) for AI. They describe such an SBOM as a structured record of an AI system's components. For each model, the record should give a hash of the weights or model file and the hash algorithm, so that the component's integrity can be validated. The SBOM itself should carry a digital signature attributable to its author.[13]

A verified model signature supplies such hashes from a known signer. Each entry in predicate.resources gives a file's algorithm and digest. The statement's subject carries one SHA-256 digest over all of them. The project intends that digest for referring to the model from other metadata documents.[6] Copy these values into the model's SBOM entry. If an SBOM you receive gives a different digest for the same file and algorithm, it describes a different file from the one the publisher signed. The model signature ties the files to the publisher, while the SBOM's signature ties the inventory to its author. Our brief on the minimum elements covers the full list.

A worked example

Sources

  1. Model Transparency README at the v1.1.1 tagGitHub, sigstore/model-transparency · 10 Oct 2025
  2. model-signing release metadata (JSON API)Python Package Index (PyPI) · accessed 20 Oct 2026
  3. Command-line interface source (_cli.py) at the v1.1.1 tagGitHub, sigstore/model-transparency · 10 Oct 2025
  4. Verification API source (verifying.py) at the v1.1.1 tagGitHub, sigstore/model-transparency · 10 Oct 2025
  5. Hashing API source (hashing.py) at the v1.1.1 tagGitHub, sigstore/model-transparency · 10 Oct 2025
  6. Signature payload source (signing.py) at the v1.1.1 tagGitHub, sigstore/model-transparency · 10 Oct 2025
  7. Changelog on the main branch at commit 087c3f5GitHub, sigstore/model-transparency · accessed 20 Oct 2026
  8. Launch of Model Signing v1.0: OpenSSF AI/ML Working Group Secures the Machine Learning Supply ChainOpen Source Security Foundation · 4 Apr 2025
  9. Sigstore Bundle FormatSigstore documentation · 14 Jan 2025
  10. CLI (Rekor transparency log)Sigstore documentation · accessed 20 Oct 2026
  11. sigstore.dev and Rekor evolutionSigstore Blog · 28 Jun 2026
  12. Rekor v2 GA - Cheaper to run, simpler to maintainSigstore Blog · 10 Oct 2025
  13. Software Bill of Materials for AI: Minimum ElementsG7 Cybersecurity Working Group, via BSI · 12 May 2026
  14. Planting Undetectable Backdoors in Machine Learning ModelsarXiv (Goldwasser, Kim, Vaikuntanathan and Zamir) · 14 Apr 2022
  15. Sleeper Agents: Training Deceptive LLMs that Persist Through Safety TrainingarXiv (Hubinger et al.) · 10 Jan 2024

Check or correct this page

Verification record

The digest below shows whether the text you are reading matches the published source. It does not show that the reporting is correct. The build computes it from this page's Markdown source and lists it in the site manifest.

11337ae7c4af15073de8411fa071df109510c56dd96756854b57a060270ce89f