The third alpha of Content Credentials. On the pure-PHP route it asks for provemark/c2pa-verifier 0.10, which fixes six ways to a wrong trusted verdict in earlier versions, and it requires provemark/content-credentials 0.20, the first library that allows it. Nothing else changes: no code, no configuration, no update hook. It is still an alpha: it has never run in production, and this project is not covered by Drupal's security advisory policy.
What changed since 1.0.0-alpha2
- The pure-PHP route needs
provemark/c2pa-verifier 0.10 (#3634250). Verifier 0.10.0 carries the fixes of a security review of its whole code; six of them are for files it wrongly called trusted, and on that route a trusted verdict is a suggestion. Since 0.9.0, a signer issued directly by a trust anchor that staples its own revoked status is invalid rather than trusted. Every provemark/content-credentials 0.19.x refuses verifier 0.9 and up, so a site on alpha2 cannot take this fix without this release.
Install or update
composer require drupal/ai_disclosure:^1.0.0-alpha3
composer require drupal/content_credentials:^1.0@alpha
# For the pure-PHP route:
composer require provemark/c2pa-verifier:^0.10
# From 1.0.0-alpha2 on the pure-PHP route:
composer require drupal/content_credentials:^1.0@alpha provemark/c2pa-verifier:^0.10 -W
drush cache:rebuild
Composer is required. AI Disclosure 1.0.0-beta1 or later is recommended. A site that keeps provemark/c2pa-verifier:^0.8 in its own composer.json stays on alpha2.
Requirements
- Drupal 11.3 or later; PHP 8.3 or later.
- AI Disclosure 1.0.0-alpha3 or later.
provemark/content-credentials 0.20.
- For the pure-PHP route,
provemark/c2pa-verifier 0.10.
Known issues
Unchanged from alpha2:
- A kept original can be read only by the PHP user, on the host, that handled the upload. A cron run as another user, or on a host that does not share
temporary://, reads the scaled file instead: no suggestion, and nothing is logged. Run cron as the web server's user.
- Sites that share one temporary directory share the kept copies: one site's cron removes another's unclaimed copies after six hours, and uninstalling the module on one site removes them all. Give each site its own temporary directory.
- An upload that another validator then refuses can leave its copy for six hours. It is never read.
drush queue:run content_credentials_read ends with an error on every run while the reading service is down; cron waits quietly. The queued files are kept either way.
- The pure-PHP verifier route is stricter than c2pa-rs on files signed elsewhere: in the library's measurement 47 of 482 files that c2pa-rs calls valid did not read valid through it, and on that route those uploads get no suggestion.
- The
ext-c2pa route skips MP3 files, because ext-c2pa v0.1.0 can end the PHP process on a malformed one: by name, and any file that begins with an ID3 tag whatever it is called (#3630240). The other routes read them. Where people you do not trust can upload files, prefer the service or verifier route.
- The
ext-c2pa route needs about 6.5 MiB of PHP memory per MB of manifest (not of file: a 13 MB photo with a normal manifest is fine). A crafted manifest of over about 10 MB per 128 MB of memory exhausts it, and the item then fails on every cron run until it is deleted. Raise cron's memory_limit, or use the verifier route, which refuses such manifests.
- Trust anchors set outside the settings form (drush, a configuration import,
settings.php) are not checked; the form checks them for both in-process routes. After changing them another way, upload one signed file and look at the log.
- The
ext-c2pa route accepts a PEM block that is not a certificate: valid base64 that does not decode to one is refused neither by the extension nor by the form, and vouches for nothing: with only such a block in the field, every upload reads as untrusted while the status report says the route works. The verifier route refuses it. If uploads you expect to be trusted log Untrusted manifest, check the anchors.
- One suggestion per entity: with several credentialed files on one entity the last one read decides. With AI Disclosure 1.0.0-alpha3 a later trusted upload sets an editor's accepted or dismissed decision back to pending; from 1.0.0-beta1 (#102, #106, #107, #108) the decision is kept when the new file reads the same, with the same grade and the same note, which names the source type, signer and software agents. A file that reads differently goes back to pending; when its grade equals the one already set, the form says so and offers only Dismiss. A file that reads lower than the grade in force gets no suggestion, and an older pending one from this module is removed. That holds even when the stricter file stays on the entity: someone who can add a trusted file that reads lower can make a pending stricter suggestion disappear. The disclosure already set is never lowered, but check the files on an entity rather than relying on a pending suggestion alone.
- Removing a credentialed file, or replacing it with one without credentials, leaves its suggestion pending; dismiss it on the entity form.
- The grade map can only reorder the grades AI Disclosure ties to a term: the form offers every grade, a row naming another grade does nothing (the log says so), and if the preferred grade is deleted the next one listed wins, which for trained-model images is AI deep fake.
- Sites that use Media opt in the media type: an image attached through Media gets its suggestion on the media item, which is where AI Disclosure keeps an image's disclosure. Each media file is read twice, once through its thumbnail.
- Translations are not handled: the suggestion is stored under the default language.
- The service route trusts the service's answer, and the form accepts an
http:// address. Use https:// unless the service runs on the same host; the status report does not warn about it yet.
- The test-root warning recognises the test root only: the status report does not warn while a certificate issued under it is among the anchors, such as the
es256 certificate in c2patool's sample folder, whose key is public too. See the README on files that another module re-signs.
- A site that re-signs uploads, such as one running C2PA Sign, needs its own certificate among the trust anchors here; otherwise every upload it signs is logged as untrusted and gets no suggestion (#3629737).
- C2PA Sign releases before 1.5.0 lose the origin of a file in the current C2PA 2.x format on the way in; no reader can recover it. Use C2PA Sign 1.5.0 or later with a current c2patool (#3632098).
- AI Disclosure 1.0.0-alpha3's
@EntityType annotations show as two deprecations on Drupal 11.4; 1.0.0-beta1 clears them.
- The service and
ext-c2pa routes read with c2pa-rs, which still calls a file trusted when its hash leaves the picture or the media outside what is signed, with the pixels changed after signing (measured by the verifier's maintainers with c2patool 0.28.1 and 0.28.2). The verifier route refuses those files. This module cannot change what c2pa-rs reports.
- Never run in production.
The full list of changes and known issues is in the CHANGELOG.