devdot
← All postsEngineering ·

Your Image Pipeline Strips C2PA Metadata by Default. That's Now a Compliance Bug.

The EU AI Act now requires machine-readable marking on AI-generated output. Most image pipelines delete that metadata during resize, and nobody has a test for it.

Since 2 August 2026, providers of generative AI systems serving the EU have to mark their output in a machine-readable format. Article 50 of the AI Act. Fines up to 15 million euros or 3% of global revenue.

The labs moved fast. Anthropic now embeds invisible watermarks in Claude text output and attaches signed C2PA provenance metadata to generated files. Google runs SynthID across text, images, audio and video. OpenAI pairs C2PA with SynthID on supported media. The C2PA coalition is past 6,000 members.

So the marking exists when the file leaves the model. The problem is what your own stack does to it next.

Your resize step is deleting the evidence

C2PA provenance lives in the file's metadata block. It is a signed manifest, and it is fragile in a very specific way: almost every image processing library strips metadata by default, because metadata is bytes and bytes are page weight.

sharp removes all metadata unless you explicitly call .withMetadata(). That is documented behaviour, not a bug. Next.js Image Optimization runs on sharp and gives you no config flag to keep it. Most CDN transform layers do the same thing for the same reason. Your thumbnail generator, your WebP conversion, your avatar cropper, your S3 upload hook that normalises orientation. Every one of those is a place where a signed provenance manifest quietly becomes a plain JPEG.

The failure mode is horrible. Nothing throws. Nothing 500s. The image renders perfectly. You only find out when someone runs a verification tool against your production URL and gets back nothing at all.

Provenance is a data integrity problem, not a legal one

Teams keep filing this under compliance and routing it to whoever owns the policy doc. That is the wrong queue. Nobody in legal is going to find the sharp call in your upload worker.

Treat it the way you treat any other value that has to survive a pipeline intact:

  • Know where AI-generated media enters your system. Model output, user uploads, third-party feeds, marketing assets pulled from a design tool. Each entry point either carries a manifest or it doesn't.
  • Audit every transform between ingest and delivery. Resize, format conversion, compression, CDN edge processing, EXIF normalisation. Assume each one strips unless you have proven otherwise.
  • Write an assertion, not a policy. Upload a known C2PA-signed asset in CI, pull it back through the full delivery path, and verify the manifest is still valid. If it isn't, fail the build.
  • Decide what you do with a stripped file. Re-sign it, reject it, or flag it. Silently serving it is the option that gets expensive.

The last point is where most of the real design work sits. If a user uploads an image with a valid manifest and your pipeline has to re-encode it, you are now the one making a provenance claim. That needs an owner.

The pattern here is older than the regulation

We have seen this exact shape before with source maps, with structured logging fields dropped by a proxy, with tracing headers lost at a service boundary. Something meaningful gets attached upstream, and an optimisation step downstream throws it away because it was optimising for a metric that didn't include it.

What changed is the cost of getting it wrong. Page weight versus a percentage of global revenue is not a close trade.

Go look at your image pipeline this week. Find the resize call. Check whether metadata survives it. It's a ten minute investigation and most teams will not like the answer.

We're here to help founders and teams design and build digital products that are built to scale with you, not slow you down. If you're looking to build something, get in contact with us today!

NEXT POST →Shopify Deletes Your Additional Scripts on August 26. Nothing Will Break Loudly.