Skip to main content

Validation states

Every result from verify falls into one of four states. Each element is { manifest, binding }; the signed states are carried on result.manifest.validation_state, typed ValidationState = "Invalid" | "Valid" | "Trusted"; the unsigned state is an empty array.

The four states

The three signed states map directly to the C2PA 2.3 §15 validation outcomes. The split is deliberate: a viewer can tell whether bytes were tampered (Invalid) apart from whether the publisher is one the application has chosen to recognize (Valid vs Trusted). Conflating the two is the most common mistake in provenance UIs, and it renders badges meaningless.

StateresultSignature intact?Chain reaches anchor?CauseUI treatment
Unsignedempty arrayn/an/aContent predates signing, nothing recoveredRender plain content, no badge
Trustedmanifest.active_manifest setyesyesSpec's terminal success stateGreen badge
Validmanifest.active_manifest setyesnoLegitimate signer in neither your anchor list nor the (default-on) C2PA conformance list, or impersonator"Signed but unverified issuer" (permissive), or treat as failure (strict)
Invalidmanifest.active_manifest setnon/aBytes modified after signing or signature did not verifySurface loudly

The difference between Valid and Trusted is the anchor set: your trust anchor list plus, by default, the bundled C2PA conformance trust list. A Valid manifest has an intact signature whose chain reaches neither. Pass trustC2paAnchors: false to make your list the only deciding set.

Don't warn on unsigned content

Do not render "not signed" warnings on most content; users quickly learn to ignore warnings that appear everywhere, which defeats the badge on content that genuinely needs one.

Failure modes

verify throws an SdkError when the bytes cannot be parsed (corrupted file, truncated download), when the registry is unreachable, or when a recovered manifest fails validation. Catch the error and show a generic "could not verify" state. An unsigned asset is not an error; it's an empty array.

When a result's manifest.active_manifest is set but result.manifest.validation_results?.activeManifest?.failure contains entries, the file was tampered. Log a failure entry for diagnostics and show the user a single "modified after signing" message.

See also