Yes. In the in-toto Statement v1 specification the predicate is optional, and unset is treated the same as set but empty. A statement can bind a subject to a predicateType alone, as long as that type fully describes what is being claimed. The subject and predicateType remain required.
The Statement in four fields
The in-toto attestation spec calls the Statement the middle layer of an attestation. It binds the claim to a subject and names the predicate type. The fields are:
| Field | Required | Meaning |
|---|---|---|
| _type | Yes | Always the Statement v1 identifier for this version of the spec |
| subject | Yes | The software artifacts the attestation applies to, each with a digest |
| predicateType | Yes | A URI identifying the type of the predicate |
| predicate | No | Extra parameters of the predicate |
Subjects are matched purely by digest. The optional name field helps tell artifacts apart inside one statement.
What "empty" means
The spec says a predicate may be omitted if the predicateType fully describes it. Think of a type that means "this artifact passed review" or "this artifact is approved for release". There may be nothing further to record. The presence of the statement, signed by the right party, is the claim.
Here is an illustrative statement with placeholder values, shown in a code block:
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{ "name": "app.tar.gz", "digest": { "sha256": "PLACEHOLDER" } }
],
"predicateType": "https://example.com/Approved/v1"
}
The example URI is invented. A real type should be one you define and document, or one from a published spec.
When an empty predicate is a good idea
- The claim is binary and the type name carries it.
- Extra fields would add noise without meaning.
- You want the smallest possible attestation for a simple gate.
When it is risky
An empty predicate gives a verifier nothing to check beyond the type and the signer. That is fine only if everyone agrees what the type means. Consider the risks:
- Ambiguity. If two teams read the type differently, one signed statement means two things.
- No context. There is no timestamp, policy name or reviewer in the body. If you need those, they belong in the predicate.
- No room to evolve. Adding fields later means a new type version, so plan the URI to include a version.
- Weak audit trail. An auditor asking what was checked has nothing to read.
A good test: could a stranger decide whether to trust this statement from the file alone? If not, add predicate fields.
How a verifier should handle it
When you consume attestations, do not skip the predicateType check. Verify the signature, confirm the subject digest matches the artifact you are about to deploy, check the type is one you expect, and then read the predicate if present. Treat an unknown type as a failure, even if the predicate is empty.
For choosing a type, see which attestation predicate type do you need. For what the subject proves, read what the subject in an attestation proves.
Safeguard's gates can require checks before a deploy, and its agent identity and evidence automation help record who attested what. The free scan is at gold.safeguard.sh/scan.
Quick check
Which fields can I never leave out?
The _type, subject and predicateType are required. The predicate is optional.
Is an attestation with an empty predicate still signed?
The statement is the middle layer. Signing happens in the envelope around it, which this spec page does not describe, so check the envelope spec.
Sources
Last reviewed: 19 October 2026.