Reference

FAQ

Scope, limits, and where attest sits next to the C2PA standard and the other tools that read it.

Questions

Is this an official C2PA implementation?

No. attest is an independent, from-scratch reader of the C2PA structures. It parses JUMBF, CBOR, COSE Sign1, and X.509 itself and verifies the parts listed on the rules page. It is not certified, not affiliated with the C2PA, and not a conformance implementation. Three gaps matter in practice: it does not evaluate c2pa.hash.boxes bindings (the BMFF fragment hashes used by video and some HEIF files), it does not check certificate revocation through OCSP or a CRL, and it does not fetch a remote manifest. Everything else it reports, it derived from the bytes on your disk.

What does "untrusted" mean?

The signature and the hard binding are fine, but no certificate in the chain matched the trust list you supplied. It is a statement about your list, not about the file. With --require-trusted the file is then reported as untrusted and exits 1; without that flag the same file reports valid. Trust is yours to define: attest does not ship a list of who is trustworthy. And if you supply no list at all, the status is unknown — not untrusted — so --require-trusted alone never fails a file.

Does it upload anything?

No. There is no network call at runtime in the CLI, the library, the MCP server, or the browser bundle. The in-page verifier reads the file with File.arrayBuffer() and does the cryptography in the tab; you can watch the network panel and see nothing leave. The only network request in the whole project is the one you type to install it or to run it through bunx.

Which file types can it read?

JPEG, PNG, and WebP, plus a standalone raw JUMBF file. For JPEG it walks the APP11 segments, for PNG the caBX chunk, and for WebP the C2PA chunk. Anything else, including MP4 and other ISOBMFF video containers, is reported as unsigned rather than parsed.

What happens if the file is unsigned?

The state is unsigned and the exit code is 1. The report says plainly that no Content Credentials were found. That is not the tool calling the file fake; it means there is no provenance to check, so its origin is unverified. If a file you expected to be signed comes back unsigned, it was stripped or it is the wrong format.

Why is the hard binding important?

The signature covers the manifest, not the pixels. If a file only had a signed manifest, someone could swap in a different image and keep the signature. The hard binding closes that gap: it is a hash of the asset's bytes, with the manifest region excluded, and attest recomputes it on every run. Change one byte outside the manifest and the binding fails while the signature still validates. That is exactly what the tampered fixture shows: signature valid, hard binding mismatch.

Does it prove the image is real?

No, and no provenance tool can. Verification answers a narrow, useful question: these bytes were signed by the holder of this key, that key chains to a certificate, and you trust that certificate. It does not establish that the scene is real, the caption is true, or the image was not generated. A trusted camera can sign a staged photo, and a genuine signature can cover synthetic content — the manifest even records an algorithmic source type when it does. Provenance is evidence about origin and integrity, not about truth.

How is trust decided?

By the trust list you pass with --trust: a JSON document or a PEM bundle. An entry matches a chain link when its SHA-256 fingerprint equals the link's certificate hash, or its subject name equals the link's subject exactly. Any link in the chain may match, so listing a root is enough. There is no built-in list and no freshness check.

Can it verify video?

Not meaningfully. attest locates manifests in JPEG, PNG, and WebP, and treats a manifest's c2pa.hash.boxes binding — used for BMFF and video fragments — as unsupported. It will report that the binding was not evaluated rather than claim a pass, but the result is not a video verification.

Does it check whether a certificate was revoked?

No. There is no OCSP or CRL request, because that would mean a network call. A certificate the issuer has since revoked will still validate here. If revocation matters to you, combine attest with a revocation-aware source of the same chain.

Does it fetch a remote manifest?

No. When a claim points at a remote_manifest URL, attest reports the URL but never requests it. The manifest it verifies is the one embedded in the file. A file whose only manifest lives at a URL is verified as far as the local bytes allow, and the remote location is surfaced for you to handle deliberately.

Who is it for?

People who want a local, second opinion on signed media: a fact-checker or archivist who should not upload a sensitive file to a service, a newsroom or platform pipeline that wants a CI gate on provenance, a developer who wants to verify bytes inside a Bun process or a web page, or an agent that needs to check a file through MCP without a shell. It is deliberately small and readable, so it can also serve as a reference for how these structures fit together.

Limitations

What attest is not

attest is a local verifier of C2PA manifests, not an official implementation and not a truth machine. It does not evaluate BMFF box hash bindings, does not check revocation, does not fetch remote manifests, and ships no trust list. It cannot tell you whether an image is authentic in the journalistic sense of depicting a real scene. It also cannot sign or edit anything: it only reads. Everything beyond reading and reporting is deliberately out of scope.