Summary
When using c2pa-python's Builder API with auto-thumbnail generation enabled
(the default), the resulting C2PA manifest places the claim thumbnail in
gathered_assertions instead of created_assertions. This violates C2PA spec
section 14.3, which requires signer-originated assertions in
created_assertions.
Reproduction
import c2pa
import io, json
signer = c2pa.create_signer(key_pem, cert_pem, "es256", tsa_url)
manifest = {"title": "test.jpg", "assertions": [
{"label": "c2pa.actions", "data": {"actions": [{"action": "c2pa.created"}]}}
]}
builder = c2pa.Builder(manifest)
dest = io.BytesIO()
builder.sign(signer, "image/jpeg", io.BytesIO(jpeg_bytes), dest)
signer.close()
dest.seek(0)
reader = c2pa.Reader("image/jpeg", dest)
detailed = json.loads(reader.detailed_json())
reader.close()
active = detailed["active_manifest"]
claim = detailed["manifests"][active]["claim"]
print(claim["created_assertions"]) # Missing thumbnail
print(claim["gathered_assertions"]) # Contains thumbnail (wrong)
Root Cause
This is inherited from the underlying c2pa-rs library. See
contentauth/c2pa-rs#2106.
In c2pa-rs/sdk/src/builder.rs, the add_assertion helper for auto-generated
thumbnails is called with created=false, routing them to
gathered_assertions.
Workaround
Option A: Disable auto-thumbnails and add them manually (loses the
convenience of auto-generation):
settings = c2pa.Settings()
settings.set("builder.thumbnail.enabled", "false")
Option B: Use created_assertion_labels in settings (requires a Context):
settings = c2pa.Settings()
settings.set("builder.created_assertion_labels", '["c2pa.thumbnail.claim"]')
context = c2pa.Context(settings=settings, signer=signer)
builder = c2pa.Builder(manifest, context=context)
Neither workaround should be necessary. The library should place its own
auto-generated assertions in created_assertions by default.
Impact
C2PA Conformance Program submissions using c2pa-python will fail review if
thumbnails are enabled. Thumbnails are optional (spec section 17.1), so
disabling them is a valid short-term fix, but conforming implementations
should be able to include thumbnails without manual routing configuration.
Summary
When using c2pa-python's Builder API with auto-thumbnail generation enabled
(the default), the resulting C2PA manifest places the claim thumbnail in
gathered_assertionsinstead ofcreated_assertions. This violates C2PA specsection 14.3, which requires signer-originated assertions in
created_assertions.Reproduction
Root Cause
This is inherited from the underlying c2pa-rs library. See
contentauth/c2pa-rs#2106.
In
c2pa-rs/sdk/src/builder.rs, theadd_assertionhelper for auto-generatedthumbnails is called with
created=false, routing them togathered_assertions.Workaround
Option A: Disable auto-thumbnails and add them manually (loses the
convenience of auto-generation):
Option B: Use
created_assertion_labelsin settings (requires a Context):Neither workaround should be necessary. The library should place its own
auto-generated assertions in
created_assertionsby default.Impact
C2PA Conformance Program submissions using c2pa-python will fail review if
thumbnails are enabled. Thumbnails are optional (spec section 17.1), so
disabling them is a valid short-term fix, but conforming implementations
should be able to include thumbnails without manual routing configuration.