When Does C2PA Disappear from AI Images Uploaded to WordPress? On This Site, Resized Images Lost It at Once and Originals After Optimization

Attaching a C2PA manifest (a standard for writing a signed record of an image’s provenance into the file) to an AI-generated image does nothing for readers if the manifest can no longer be read once the image is on a blog. On how WordPress C2PA data holds up, issue #421 in WordPress’s official AI plugin says that the C2PA manifest gets broken at the stage where resized images are created, whether GD or Imagick is used. That, however, is the issue author’s description, not a WordPress core document. So we uploaded test images to the WordPress install that runs this site, swiftwand.com, then re-fetched and counted both the original (the uploaded file itself) and the resized images (the sizes WordPress generates).
This article contains affiliate links. As an Amazon Associate, we earn from qualifying purchases.
The test images are one PNG and one JPEG, both 1280×720. As metadata written into the file we added the ComfyUI generation record (PNG only), EXIF (JPEG only), XMP and C2PA; as a watermark embedded in the pixels we added TrustMark. We uploaded them through the REST API and re-fetched the original and every size WordPress created, once right after upload and again 17 minutes later. EWWW Image Optimizer 8.9.1, an image optimization plugin, is active on this site’s WordPress, so the results are for the combination of WordPress core and EWWW.
Here are the results up front. The resized images had no C2PA from the moment of upload, for both PNG and JPEG, in all 7 files (8 by size name). The originals were unchanged right after upload, and C2PA validation returned Valid. Seventeen minutes later, however, both originals had been replaced with files that had identical pixels and fewer bytes, and C2PA, the generation record, XMP and EXIF were all gone. The TrustMark watermark stayed readable to the end in the originals and in the non-square resized images.
After measuring, we deleted the test images and confirmed that the URLs of the original and of every size returned 404. Each condition was run once, so we cannot claim more than “this is what happened in this run.” This article does not cover legal questions such as Article 50 of the EU AI Act and is not legal advice. The dates of the laws and a count of records across this site’s whole image pipeline are in Where AI-generated labels and “marks” disappear in images and 3D data (published 2026-11-09).
- Why C2PA breaks on resizing — hard binding is a hash of the bytes, and a resized image is a different file
- How WordPress core creates resized images — default sizes, quality 82 and image_strip_meta
- The image optimization plugin EWWW Image Optimizer also processes originals
- Conditions for the WordPress C2PA measurement — PNG and JPEG with metadata and a watermark, uploaded via REST
- Result 1 — resized images had no C2PA right from upload
- Result 2 — originals survived at first, but 17 minutes later had been replaced with smaller files with identical pixels
- Result 3 — TrustMark could not be read only in the square-cropped sizes
- Why this site’s published images had no generation record — post-upload optimization and resends by the publishing script
- How to read the results — this is “core + EWWW,” not WordPress core alone
- What this WordPress C2PA measurement cannot tell you
- Summary
- Sources
Why C2PA breaks on resizing — hard binding is a hash of the bytes, and a resized image is a different file
A C2PA manifest uses a hash to point to the bytes it signed. The specification (C2PA Technical Specification 2.5, October 2026) calls this a hard binding and defines it as a cryptographic hash that uniquely identifies all or part of an asset. It then states that a hard binding matches only that asset, and not assets derived from it or other versions (renditions) made from it.
What the hash is computed over is also defined. A data hash (c2pa.hash.data) is computed over the asset’s bytes, excluding the ranges set aside as the manifest’s location. Because it covers bytes rather than pixels, re-compressing an image changes the byte stream and breaks the match even when the image looks the same. When it does not match, validation returns assertion.dataHash.mismatch. Moreover, the specification says that when there is a mismatch, it cannot tell whether the asset was modified or a different manifest was picked up.
For box-based formats such as JPEG and PNG, a per-box hash (c2pa.hash.boxes) is also recommended. Either way, a resized image is a different file whose pixel count and byte stream both differ from the original. Even if WordPress copied the manifest into a resized image, the manifest would not match that resized image. In other words, C2PA becoming unusable on resizing is first of all a consequence of how C2PA itself works. The steps for writing an “AI-generated” marker with c2patool and reading the validation results are in Adding provenance to AI images with C2PA and reading it back (published 2026-11-10).
Where the manifest is stored differs by format. According to Appendix A.3 of the specification, in JPEG it goes into APP11 marker segments; one segment cannot exceed 64K bytes, so a large manifest is split across several. In PNG it goes into a chunk called caBX. caBX is an ancillary, private, not-safe-to-copy chunk, placed before the image data (IDAT).
That “not safe to copy” matters for PNG. The PNG Specification 1.2 says that chunks that are not safe to copy (whose safe-to-copy bit is 0) depend on the image data. It further says that an editor that has changed critical chunks such as IDAT must not copy unknown chunks of that kind to its output. Resizing regenerates the image data, so a spec-compliant editor will not carry caBX over into a resized image.
One more point: C2PA recommends including metadata outside the manifest, such as EXIF and XMP, in the hard binding where possible. If it is included, losing only the EXIF or the XMP can be enough to make validation fail. How the test images’ manifests handled them was not examined in this run.
How WordPress core creates resized images — default sizes, quality 82 and image_strip_meta
WordPress core picks the image processing implementation used for resizing from a list of candidates. By default the candidates are Imagick first and GD second, and the first one that meets the conditions is used. The condition for Imagick is not just whether the extension is installed. In 7.1.4, test() checks that the PHP imagick extension is loaded and also that the Imagick class, the extension version (2.2.0 or later), the JPEG compression constant, and the methods used for resizing, writing and so on are all present. When choosing, WordPress also checks whether the target image format is supported (supports_mime_type()). So by default it prefers Imagick if Imagick meets the requirements and supports the target format, and tries GD if not. Imagick may not be chosen even when the extension is installed.
Which one is chosen is shown in the Site Health info screen in the admin, under “Media Handling,” as “Active editor.” The value in that field, however, is the result of choosing without specifying a format, so it does not include the per-format support check (both points confirmed in the 7.1.4 code).
The default sizes of the resized images are as follows. They change with site settings and the theme, so the sizes actually created on this site are given in the measurement section.
| Size name | Default width | Default height | Crop |
|---|---|---|---|
| thumbnail | 150 | 150 | Yes |
| medium | 300 | 300 | No |
| medium_large | 768 | 0 (no limit) | No |
| large | 1024 | 1024 | No |
| 1536×1536 | 1536 | 1536 | No |
| 2048×2048 | 2048 | 2048 | No |
Images whose width or height exceeds 2560 px also go through -scaled processing. WordPress creates a reduced copy with -scaled appended to the file name, points the attachment at that copy, and keeps the original file, recording it as original_image. The resized images are generated from the original, not from the -scaled copy. The test images are 1280×720, so this did not happen. Images over 2560 px were not tested.
The default quality is 82 (86 for WebP), a value lowered from 90 in version 4.5 in 2016. By default the only change of output format is HEIC/HEIF to JPEG; PNG and JPEG are resized in their original formats.
For metadata there is a filter called image_strip_meta. It decides whether metadata is removed during resizing, and it defaults to true (remove). This filter only takes effect when resizing with Imagick, though. The code comment explains that this is because GD always strips profiles by default.
Even when Imagick strips metadata, it does not strip everything. strip_meta() in 7.1.4 holds a list of the following five profiles to keep and removes any profile not on the list.
- icc and icm: color profiles
- iptc: information such as copyright
- exif: information such as orientation
- xmp: information such as rights and terms of use
APP11 in JPEG, the container for C2PA, is not on this list. When resizing a PNG, the code says it removes unneeded chunks in addition to applying compression settings, and for a normal (non-palette) PNG it writes the file with png:exclude-chunk set to all. In the ImageMagick 7.1.2-35 source (coders/png.c), all excludes ancillary chunks such as tEXt, zTXt, tIME, cHRM and bKGD and the date text (date), and chunks ImageMagick does not know are not written regardless of this setting. The name caBX does not appear anywhere in png.c, so caBX counts as an unknown chunk. We did not check the ImageMagick version on this site’s server, so what actually survived is shown by the measurements.
As for the original, the upload handling in 7.1.4 (wp-admin/includes/image.php) generates the resized images from the original file. The -scaled copy and a version rotated to match the EXIF orientation (-rotated) are also saved as separate files, and the original file is recorded as original_image. Reading the code, WordPress core does not alter the original file even when it creates resized images. The developer note for 4.5 also says, about that version’s changes to resized images, that the full-size images uploaded to WordPress are not affected by the change.
The claim that resizing breaks C2PA comes from WordPress’s official AI plugin (the WordPress/ai repository). Issue #421, “WordPress should detect C2PA manifests on upload” (opened 2026-04-12), says that C2PA is broken at the resize stage with both GD and Imagick, and that while the original file remains on disk, the opportunity to read the manifest is at upload time. The issue was closed as completed on 2026-10-08 when PR #459 was merged. PR #459 likewise says that APP11 does not survive GD or Imagick re-saves, and that the original bytes are intact only at upload time.
The feature from this PR shipped in AI plugin 1.5.0 (2026-10-30) as an experimental feature named “Content Verification.” It detects C2PA in uploaded JPEG, PNG and WebP files in a read-only way and stores it with the attachment; cryptographic validation and full JUMBF/CBOR parsing are deferred. The readme states explicitly that the plugin is not part of WordPress core and that experimental features may change significantly or be removed from version to version. This does not mean WordPress supports C2PA. WordPress core’s issue tracker (core trac) also has ticket #65952, but we could not confirm its contents for this article, so it is only linked in the sources at the end.
The image optimization plugin EWWW Image Optimizer also processes originals
EWWW Image Optimizer, which is active on this site, is at version 8.9.1 (2026-10-29), the latest release. According to the readme it removes metadata by default, and the setting is called “Remove Metadata.” The settings screen describes it as removing everything that is not pixel data, such as EXIF, comments and color profiles, and the official documentation says that anything that does not tell the computer how to draw the pixels is removed from the image. When the Compress API or Easy IO is used, however, color profiles are kept regardless of this setting.
The big difference from core is that originals are processed too. The official documentation says images uploaded to the Media Library are optimized automatically. The readme FAQ answers the question of whether it replaces existing images by saying that it does so only when the optimized version is smaller, and it also says the plugin never creates a larger image. Core leaves originals alone, but on a site with EWWW the original file can be replaced as well. Metadata removal also applies to both originals and resized images.
EWWW also adds its own image processing implementations to the front of core’s candidate list. These inherit from core’s Imagick implementation and call image_strip_meta in the same way when resizing. The resizing routine (thumbnail_image()), however, is overridden, and PNG handling differs from core. The setting that removes ancillary chunks (png:exclude-chunk set to all) is applied only to palette PNGs without transparency; normal PNGs get only compression settings.
In the default state with automatic optimization enabled, the code indicates that Site Health’s “Active editor” shows EWWWIO_Imagick_Editor or EWWWIO_GD_Editor (or EWWWIO_Gmagick_Editor if the Gmagick editor class WP_Image_Editor_Gmagick, which is not among core’s default candidates, is loaded).
Upload-time processing (shrinking images that exceed the maximum dimensions, and automatic rotation; the default maximum is 2560×2560) hooks into wp_handle_upload. That filter also runs when the file body is sent through the REST API.
When looking at older images, the 8.9.0 (2026-10-13) changelog matters. It includes a fix for PNG metadata not being removed when optipng on the server was used. In other words, until the fix in 8.9.0, there was a bug where PNG metadata was not removed in setups using optipng on the server. The changelog does not say from which version. We have not confirmed whether this site optimizes with tools on the server or through the API.
EWWW is not the only thing that removes metadata. Core also removes it during resizing: always with GD, and anything outside the list with Imagick. We did not look into other optimization plugins. We also did not read this site’s EWWW settings screen, so what follows describes behavior only, not settings.
Conditions for the WordPress C2PA measurement — PNG and JPEG with metadata and a watermark, uploaded via REST
The test images are based on the cover image of this site’s 2026-11-02 article (a PNG generated with ComfyUI, 1280×720). We kept the same dimensions as this site’s article images, because what we want to know is what actually happens to this site’s images. The records were added in the following order. C2PA locks down the pixels and the bytes, so it was added last.
- Watermark: embed the value
sw1102with TrustMark (variant Q) - Metadata: in the PNG, keep the generation record written by ComfyUI (the
prompttext) and write XMP in an iTXt chunk with the IPTCIptc4xmpExt:DigitalSourceTypeset totrainedAlgorithmicMedia(the value that indicates an image made with generative AI). In the JPEG (quality 95), write the EXIF ImageDescription and XMP with the same content - C2PA: sign with c2patool’s test key. Add the AI-generated marker (the digitalSourceType on
c2pa.created) with--create trainedAlgorithmicMedia, and add ac2pa.ai-disclosurenaming the model used, in the form"created": true. No timestamp is added
The resulting PNG was 939,713 bytes and the JPEG 222,821 bytes. The signatures use the test key bundled with c2patool, not a real signing certificate. The validation result is therefore “the signature and tamper checks passed (Valid), but it is not Trusted because the signer is not on a trust list.” Note that Valid confirms the file has not been changed since signing; it is not proof that the image was generated by AI.
The upload method was to send the file bytes as they are to the REST API’s POST /wp/v2/media. The upload did not go through this site’s publishing script (deploy.py), and the images were not attached to any post. The request looked like this.
POST /wp/v2/media
Content-Disposition: attachment; filename=<file name>
(the body is the raw bytes of the file)The PNG was uploaded at 12:22:58 and the JPEG at 12:23:00 (2026-11-02), and both returned HTTP 201. By default the REST API in 7.1 creates resized images on the server, so what was measured is server-side processing. The response’s media_details.sizes listed 9 size names, including full.
| Size name | Dimensions created on this site |
|---|---|
| thumbnail | 150×150 |
| post-thumbnail | 150×150 |
| medium | 300×169 |
| small_size | 320×180 |
| thumbnail_size | 320×320 |
| medium_size | 640×360 |
| medium_large | 768×432 |
| large | 1024×576 |
| full | 1280×720 (same dimensions and byte count as the original) |
Some of these names are not among core’s defaults (post-thumbnail, small_size, thumbnail_size and medium_size). We did not check where these sizes were registered. 1536 and 2048 were not created because they are larger than the source. thumbnail and post-thumbnail pointed to the same 150×150 file (the same URL), and full pointed to the original file itself. So the resized images number 8 by size name and 7 by file. The counts below are by file; only the tables have one row per size name.
We read the files twice: first right after upload (12:23:03), then 17 minutes later (12:40:03). The 17 minutes comes from 12:40:03 − 12:23:03. We had decided in advance to read twice in case EWWW processes images in the background after a delay. Each time, we re-fetched the original and every size from the URLs in the response. We then searched the files for text, EXIF, XMP and C2PA boxes with this site’s script, read the C2PA status with c2patool, and read the watermark with TrustMark.
Result 1 — resized images had no C2PA right from upload
The results right after upload (12:23:03) are summarized below.
| File | C2PA | Generation record (prompt) | XMP (standard location) | EXIF | TrustMark |
|---|---|---|---|---|---|
| PNG original (939,713 bytes) | Valid | Present | Present | — (none to begin with) | Readable |
| PNG resized images (7 files, 8 by size name) | Absent in all 7 files | Present in all 7 files | Absent in all 7 files (present as reformatted text) | — | Readable except in the 2 square files |
| JPEG original (222,821 bytes) | Valid | — | Present | Present | Readable |
| JPEG resized images (7 files, 8 by size name) | Absent in all 7 files | — | Present in all 7 files | Present in all 7 files | Readable except in the 2 square files |
None of the resized images, PNG or JPEG, had a C2PA box. Reading them with c2patool gives “No claim found,” meaning that no manifest was found. This agrees with what the official AI plugin’s issue #421 and PR #459 say. It is, however, a single result for this site’s combination, not something written down as a specification of WordPress core.
Right after upload, both originals had the same byte count as the uploaded files. C2PA validation stayed Valid, and the generation record, XMP, EXIF and TrustMark were all intact. This matches the reading of 7.1.4’s image.php that core’s upload handling does not alter the original file, and at this point, fetching the file from the original’s URL would have let you read the C2PA.
The PNG resized images showed a different kind of change. The generation record, prompt, survived. XMP, however, was not in its standard location, the iTXt XML:com.adobe.xmp, but had turned into text under the key Raw profile type xmp. In addition, date:create, date:modify and date:timestamp text entries had been added.
This is how ImageMagick writes PNGs. It appears that ImageMagick was used for resizing, but we did not read Site Health’s “Active editor,” so we do not state it as fact. The contents of Raw profile type xmp were the same string as the original XMP, written out in hexadecimal. Still, tools that look for XMP in its standard location will not see the XMP in these resized images.
Also, the PNG resized images right after upload kept prompt and had cHRM, bKGD and tIME chunks added. All of these are chunks that all excludes in the 7.1.2-35 png.c, so the setting that removes ancillary chunks evidently was not in effect for this resize. Core’s code applies that setting to normal PNGs, but EWWW 8.9.1’s implementation applies it only to palette PNGs. The test PNG has color type 2 (RGB) and is not a palette image. If it was resized by EWWW’s implementation, the surviving prompt is consistent with the code. But we did not read “Active editor,” so we do not state which implementation was used.
The JPEG resized images, on the other hand, kept EXIF and XMP in all 7 files. This is consistent with exif and xmp being on Imagick’s keep list, but we do not treat it as evidence of which implementation did the resizing either.
Result 2 — originals survived at first, but 17 minutes later had been replaced with smaller files with identical pixels
When we re-fetched them 17 minutes later (12:40:03), both originals had become different files. The PNG had shrunk from 939,713 bytes to 814,653 bytes, and the JPEG from 222,821 bytes to 157,338 bytes. The reductions are (939,713 − 814,653) ÷ 939,713 = 125,060 ÷ 939,713, or about 13.3%, for the PNG, and (222,821 − 157,338) ÷ 222,821 = 65,483 ÷ 222,821, or about 29.4%, for the JPEG.
Meanwhile, the RGB pixels matched the files from right after upload exactly (the maximum per-pixel difference was 0). The appearance did not change; only the bytes did. The replaced originals contained none of C2PA, the generation record, XMP or EXIF. The TrustMark watermark could still be read.
WordPress core’s upload handling does not alter the original file (as read from 7.1.4’s image.php). What replaced it appears to be EWWW’s optimization, which is active on this site (we did not read EWWW’s own processing logs). The outcome, with identical pixels, a smaller file and all non-pixel metadata gone, matches EWWW’s documented defaults (remove metadata, replace only when smaller). When between 12:23 and 12:40 the replacement happened cannot be told from these two reads. All we can say is that it did not happen immediately on upload but later, in the background.
Some of the resized images had also been replaced after 17 minutes.
| PNG size | Dimensions | Bytes right after upload | Bytes after 17 minutes | Text after 17 minutes |
|---|---|---|---|---|
| Original | 1280×720 | 939,713 | 814,653 | None |
| thumbnail | 150×150 | 26,221 | 24,493 | None |
| post-thumbnail | 150×150 | 26,221 | 24,493 | None |
| medium | 300×169 | 50,112 | 48,354 | None |
| small_size | 320×180 | 56,085 | 54,308 | None |
| thumbnail_size | 320×320 | 96,818 | 94,767 | None |
| medium_size | 640×360 | 185,363 | 183,429 | None |
| medium_large | 768×432 | 271,265 | 269,408 | None |
| large | 1024×576 | 473,176 | 470,868 | None |
All 7 PNG resized files had shrunk, and prompt, Raw profile type xmp and the date text were all gone.
| JPEG size | Dimensions | Bytes right after upload | Bytes after 17 minutes | EXIF and XMP after 17 minutes |
|---|---|---|---|---|
| Original | 1280×720 | 222,821 | 157,338 | None |
| thumbnail | 150×150 | 4,318 | 3,920 | None |
| post-thumbnail | 150×150 | 4,318 | 3,920 | None |
| medium | 300×169 | 7,675 | 7,277 | None |
| small_size | 320×180 | 8,398 | 7,997 | None |
| thumbnail_size | 320×320 | 12,744 | 12,596 | None |
| medium_size | 640×360 | 23,062 | 23,062 | Present |
| medium_large | 768×432 | 31,436 | 31,436 | Present |
| large | 1024×576 | 48,964 | 48,964 | Present |
In the JPEG resized images, EXIF and XMP were gone in 4 of the 7 files (medium, thumbnail = post-thumbnail, thumbnail_size and small_size). The remaining 3 files (medium_size, medium_large and large) had the same byte counts as right after upload and still had EXIF and XMP. These 3 files appear not to have been replaced. EWWW says it replaces a file only when the optimized version is smaller, but why these 3 files were not replaced cannot be determined from this record.
In summary, in this run C2PA was absent from the resized images from the start, and it also disappeared from the originals after optimization. The generation record, XMP and EXIF were mostly intact right after upload, but 17 minutes later they were gone everywhere except in the 3 larger JPEG files.
Result 3 — TrustMark could not be read only in the square-cropped sizes
The TrustMark watermark held up differently from the metadata.
| File | Right after upload | After 17 minutes |
|---|---|---|
| Original (1280×720) | Readable | Readable |
| Non-square resized images (300×169, 320×180, 640×360, 768×432 and 1024×576) | Readable | Readable |
| Square-cropped resized images (2 files: 150×150 and 320×320) | Not readable | Not readable |
PNG and JPEG gave the same results. In the original and in the resized images that kept the aspect ratio, the watermark was readable both right after upload and after 17 minutes. Both the originals and the resized images had the same pixels right after upload and 17 minutes later, so it makes sense that the result did not change.
The only files in which it could not be read were the 2 square-cropped files (150×150 and 320×320; 3 by size name), and that held both right after upload and after 17 minutes. Whether a watermark can still be read after resizing and JPEG compression was tested on local processing in Do watermarks on AI images survive resizing and compression? (published 2026-11-11), but square cropping was not tested there. Why square cropping made it unreadable was not investigated in this run.
A watermark is not the C2PA manifest itself. There is a mechanism (soft binding) that uses it as an identifier to look up a lost manifest in a repository, but we leave its role to the watermark article above. This site does not run a manifest repository, so what we checked here goes only as far as whether the value could be read after resizing and optimization.
Re-reading a watermark like this is easy to repeat on your own site if you can process images in bulk with Python. A practical automation book is a good starting point.
Why this site’s published images had no generation record — post-upload optimization and resends by the publishing script
When we re-fetched this site’s published article images from their public URLs, the generation record was nowhere to be found. Of the local article images (the PNGs in images/), 2,816 of 2,862 carried ComfyUI’s prompt, yet in 3 posts (IDs 14099, 14161 and 14233), none of the 29 originals and 203 resized images (232 counted by size name) had prompt. All 29 originals matched the local files pixel for pixel in RGB, all of them differed in their bytes, and their only chunks were IHDR, IDAT and IEND.
This pattern is exactly the same as the replacement in Result 2: identical pixels, changed bytes, and every non-pixel chunk gone. If the published images also lost their generation records to optimization after upload, that would explain it.
There is, however, one more path by which the records can disappear. When this site’s publishing script (deploy.py) sends an image, it first sends the original bytes as they are. Only when the WAF in front of the server (a system that inspects requests and rejects some of them) returns 403 does it re-save the image as PNG with Pillow and send it again, trying compression levels 1, 3, 6 and 9 in that order.
This re-save calls convert("RGB") and then saves as PNG without passing pnginfo. In Pillow, PNG text chunks are written at save time through pnginfo, so reading the code, the resent PNG carries neither the generation record text nor caBX. deploy.py does not always erase the records; they are lost only when it resends after a 403. This site has not yet changed this resend behavior.
Which published images went through a resend cannot be told from the files. A resend leaves the pixels the same, and EWWW’s processing also reduces the chunks to IHDR, IDAT and IEND. We also did not keep a record at publishing time of whether a resend happened. So for the published images, all we can say is that the files at the public URLs had no records. In the test images, the records were lost in a replacement that appears to be post-upload optimization. But since we cannot tell whether each past image lost its records at the resend before upload or at the optimization after upload, we do not settle on a single cause.
Also, 25 of the local images from January 2026 were made before we started using ComfyUI and carried Google’s C2PA (the organization name on the signing certificate was Google LLC, and the digitalSourceType was trainedAlgorithmicMedia). The published images for the 2 posts from that period (IDs 1868 and 1931) were uploaded as JPEG and had no C2PA, EXIF or XMP. They are in a different format from the local PNGs, so at which stage the data was lost cannot be said from this record. The image generation workflow (ComfyUI and licensing) is described in Covering Your Article Images Locally — ComfyUI, FLUX, and Reading the Licence Right (published 2026-08-27).
How to read the results — this is “core + EWWW,” not WordPress core alone
When reading these WordPress C2PA results, the first thing is not to get the subject wrong. Everything so far happened with the combination of “WordPress core + EWWW Image Optimizer 8.9.1,” so we cannot write that “WordPress removes C2PA.” This site’s WordPress version appears to be 7.1.4, judging from the version string on the core scripts that public pages load (ver=7.1.4), but we did not confirm it in the admin screen.
The change to the originals appears to come from EWWW’s optimization; core does not alter originals. The absence of C2PA in the resized images is consistent with how C2PA works (hard binding is a hash of the bytes and does not match derived versions), with PNG’s rule on not-safe-to-copy chunks, and with what the AI plugin’s issue and PR say. Even so, C2PA being lost on resizing is not something written as a specification in WordPress core’s documentation.
We could not tell whether GD or Imagick did the resizing on this site. The ImageMagick-style text added to the PNG resized images suggests that Imagick was used, and that is as far as we go. Nor can the presence or absence of metadata tell them apart. With core’s Imagick, EXIF and XMP should remain in JPEG resized images, but EWWW’s metadata removal also applies to resized images. So with either GD or Imagick, the end result over time can be the same: the data disappears. Confirming it would start with reading Site Health’s “Active editor,” which we did not do this time.
The upload method also limits the scope. This time we used the REST API’s default upload, and the server created the resized images. In WordPress 7.1’s block editor, a mechanism that creates resized images in the browser is enabled by default in supported browsers. In that case the server-side image processing implementation is not used, and EWWW’s documentation also says some of its processing does not run. We did not measure how images uploaded from the block editor fare.
Timing also affects the reading. The official AI plugin’s PR said that the original bytes remain only at upload time. In this run on this site, the original was still the uploaded file right after upload and had been replaced 17 minutes later. For this run only, the original’s C2PA could be read only in the window between upload and the replacement by optimization.
To check the same thing on your own site, the procedure comes down to these 4 steps.
- In Site Health, read “Active editor” under “Media Handling” to see which implementation is used for resizing
- Check whether an image optimization plugin is installed and whether it is set to remove metadata
- Upload one test image with C2PA, then, right after upload and again after some time has passed, re-fetch the original and each size and read them with c2patool
- When you have finished measuring, delete the test image and confirm that its URLs can no longer be fetched
What this WordPress C2PA measurement cannot tell you
- Each condition was run once. This is the result of uploading one PNG and one JPEG, once each, and we cannot say it would turn out the same every time, even on the same site
- It is the result for this site’s combination. It is not a result for WordPress core alone, or for sites with a different optimization plugin. We did not read the EWWW settings screen or Site Health’s “Active editor,” so we cannot say which settings produced this
- We did not determine GD versus Imagick. The ImageMagick-style text suggests Imagick, and that is as far as we go
- The time of the replacement is unknown. We read only twice, at 12:23 and 12:40, so we cannot say when in between the replacement happened
- Only 1280×720 images were tested. Images over 2560 px (
-scaled), palette PNGs, images with an EXIF orientation and WebP were not tested - Only uploads through the REST API were tested. Uploads from the block editor or the admin screen were not measured
- We did not investigate why TrustMark could not be read in the square crops
- The images were signed with a test key. The Valid result was obtained with a signer that is not on a trust list, and it is not Trusted. This site’s article images carry neither C2PA nor a watermark
- No legal judgment is made. We do not say what any site is required to do
After measuring, we deleted both test images. After deletion, we confirmed that the URLs of the original and of all sizes (for both PNG and JPEG, 8 each: 1 original and 7 resized images), as well as fetching them via REST, all returned 404.
Summary
Measuring how WordPress C2PA data holds up on this site, we found it disappeared at two stages. The first was the resized images: from the moment of upload, none of the 7 resized files had C2PA, for both PNG and JPEG. A resized image is a different file whose bytes and pixel count both differ from the original, so even if the manifest were copied over, the hard binding would not match. The second was the original: right after upload it was still the uploaded file and C2PA was Valid, but 17 minutes later it had been replaced, by what appears to be image optimization, with a smaller file with identical pixels, and all its metadata was gone.
The TrustMark watermark embedded in the pixels stayed readable to the end in the original and in the resized images that kept the aspect ratio. The only files in which it could not be read were the 2 square-cropped files. In this one run, the metadata was lost to an optimization that left the pixels unchanged, while the watermark survived optimization and became unreadable with square cropping. Metadata and the watermark disappeared at different stages.
If you put AI images on a blog and want C2PA to reach your readers, you need to check two stages on your own site: the resized images and the optimization of the original. Studying WordPress core’s behavior alone is not enough, because the result can change with the plugins you have installed. Upload one test image, re-fetch the original and each size after some time has passed, and read them, and you will see what disappears at which stage on your site.
Sources
- C2PA Technical Specification 2.5 (October 2026)
- PNG Specification 1.2, “3. File Structure” (libpng.org)
- IPTC “Digital Source Type” vocabulary
- WordPress 7.1.4 class-wp-image-editor-imagick.php
- WordPress 7.1.4 class-wp-image-editor-gd.php
- WordPress 7.1.4 class-wp-image-editor.php
- WordPress 7.1.4 wp-includes/media.php
- WordPress 7.1.4 wp-admin/includes/image.php
- WordPress 7.1.4 wp-admin/includes/schema.php
- WordPress 7.1.4 wp-admin/includes/file.php
- WordPress 7.1.4 class-wp-debug-data.php
- WordPress 7.1.4 REST attachments controller
- developer.wordpress.org, “image_strip_meta”
- developer.wordpress.org, “wp_image_editors”
- developer.wordpress.org, “big_image_size_threshold”
- developer.wordpress.org, “WP_Image_Editor”
- REST API Handbook, “Media”
- Make WordPress Core, “Performance improvements for images in WordPress 4.5” (2016-03-12)
- Make WordPress Core, “Client-Side Media Processing in WordPress 7.1” (2026-07-22)
- WordPress/ai issue #421, “WordPress should detect C2PA manifests on upload”
- WordPress/ai PR #459, “Add C2PA Monitor experiment”
- WordPress/ai release 1.5.0
- AI plugin 1.5.0 readme.txt
- AI plugin 1.5.0 documentation for Content Verification
- WordPress core trac #65952
- EWWW Image Optimizer (plugin page on wordpress.org)
- EWWW Image Optimizer 8.9.1 readme.txt
- EWWW Image Optimizer 8.9.1 classes/class-plugin.php
- EWWW Image Optimizer 8.9.1 common.php
- EWWW Image Optimizer 8.9.1 classes/class-ewwwio-imagick-editor.php
- docs.ewww.io, “How to use EWWW Image Optimizer”
- docs.ewww.io, “Basic Configuration (Essentials)”
- docs.ewww.io, “Advanced Configuration”
- Pillow, “Image file formats”
- ImageMagick 7.1.2-35 coders/png.c





