← Back to all posts
News

Paint's AI Runs on Your NPU. The GUID Comes From Redmond.

August 25, 2026 · 00:09 UTC · News
Paint's AI Runs on Your NPU. The GUID Comes From Redmond.

TL;DR

On August 20 reverse engineer Xusheng Li published a teardown of Microsoft Paint and Windows Photos showing what happens when you generate an image with Cocreator on a Copilot+ PC. The render runs on your NPU. The identity stamped into it does not. Paint posts your prompt to a Microsoft moderation endpoint first, and the response hands back a watermarkId: a GUID minted server side. Watermarker.dll then writes that GUID into your pixels as an 18-byte invisible payload, and the signed C2PA manifest records the same GUID as a soft-binding under the algorithm name com.microsoft.invismark.1. The post hit the Hacker News front page on August 24 with 522 points. One scope correction up front, because the headline going around overstates it: only AI-generated and AI-edited images get marked, not your ordinary Paint doodles.


The round trip you did not know about

Cocreator is the marquee "it runs on your device" feature of Copilot+ PCs. It does run on your device. It is not offline.

Before the local model produces a single pixel, Paint sends the prompt to /v1/paint-cocreator/moderate-prompt on a Microsoft Azure Front Door host. The request carries prompt, style, and lastPromptGenerationId. The response carries four fields: revisedPrompt, promptGenerationId, watermarkId, and containsHumanReference.

So the server does three things in one call. It rewrites your prompt, it opens a record keyed by a generation ID, and it issues the identifier that is about to be baked into your image. Li verified this by reusing Paint's own authenticated session: the prompt "a cobalt blue circle above a tiny orange square" came back with watermarkId: 83424621-03cb-40e3-9808-a9fae837156d.

The mental model most people have of on-device generation is a photocopier: paper in, paper out, nobody else involved. The real model here is closer to a home printer that prints locally but has to phone the manufacturer for the serial number it stamps in the margin, and the manufacturer keeps a note of what you asked to print.

one Cocreator generation, end to end your prompttyped in Paint Microsoft servermoderate-prompt returns watermarkIda 16-byte GUID local NPUrenders image Watermarker.dllembeds 18 bytes C2PA manifestsoft-binding = GUID
The generation is local. The identifier is not, and it arrives before the model runs.

Eighteen bytes, and sixteen of them came from a server

The payload Paint writes into the image is small and rigid: a single header byte 0x4c, then the 16 GUID bytes, then one checksum byte that is the sum of those 16 bytes modulo 256. Eighteen bytes, 144 bits.

The embedding function, WmkWriteWatermark, validates hard. Pass a payload that is not exactly 16 bytes and you get error -6 for too short or -5 for too long. Images smaller than 192 by 192 are rejected outright. Li describes the embedding itself as content-adaptive and block-domain, an SVD-style transform applied across 8-pixel boundaries, requiring at least three successful bit placements per position. That redundancy is the point: a mark that only lives in one place dies the first time someone crops or re-saves.

the 18-byte payload written into your image hdr 16-byte watermarkId issued by the moderation server sum 4c 83424621-03cb-40e3-9808-a9fae837156d ck rejected unless the payload is exactly 16 bytes: -6 short, -5 long minimum image size 192 x 192
A header, a server-issued GUID, and a one-byte checksum. That is the whole message.

What it actually does to the picture

On a synthetic 512 by 512 BGRA test image, Li measured 193,376 of the 262,144 pixels changed after watermarking. That is 73.8 percent of the frame touched to hide 144 bits.

It is still invisible, and that is not marketing. The algorithm named in the manifest, InvisMark, is Microsoft's own published work: a WACV 2025 paper reporting PSNR around 51 and SSIM around 0.998 with over 97 percent bit accuracy across manipulations, and a 256-bit payload ceiling. The MIT-licensed repo ships a pretrained model with 100 encoded bits and no error correction, so the shipping Windows version is not the same artifact, but the family is the same.

512x512 test image: pixels touched by the watermark 193,376 altered (73.8%) 68,768 untouched 144 bits carried, of which 128 are the GUID itself InvisMark paper reports PSNR ~51 and SSIM ~0.998 pervasive in the data, invisible to the eye
Three quarters of the pixels move so that 144 bits survive a re-save.

Paint fails closed. Photos fails open.

The same Watermarker.dll ships in both apps, but they disagree about what to do when the stamp will not stick.

Paint treats a WmkWriteWatermark failure as a failure of the entire generation and refuses to hand you the image. Photos logs the error and returns the picture anyway, unmarked. Two teams, one binary, two opposite answers to the same question. If you were counting on the mark being present on every AI-touched file that leaves a Windows box, that assumption holds in one app and not the other.

What Microsoft documents, and what it leaves out

Microsoft is not hiding the general shape of this. The official Paint application card on Microsoft Learn says plainly that "Cloud services are used to provide safety systems, including content filtering," that "On-device features such as Cocreator perform image generation locally on supported devices," and that "Images generated using generative AI include content credentials based on the C2PA standard."

Three things it does not say:

  • That an invisible pixel-level watermark exists at all, separate from the metadata.
  • That the identifier in that watermark is issued by the prompt-moderation service, not generated on your machine.
  • That the file-level manifest and the pixel-level mark carry the same GUID, which makes them two views of one record rather than two independent labels.

The manifest itself is not shy about it once you look: the action is c2pa.watermarked, described as "Content watermarked by Microsoft Responsible AI," with the soft-binding value set to the watermark GUID. It is documented in the file. It is just not documented to the user.

Why any of this exists

Article 50 of the EU AI Act started applying on August 2, 2026, and it requires AI-generated content to carry a machine-readable mark. C2PA metadata alone is a poor answer to that requirement, because sidecar metadata evaporates the moment a file goes through a screenshot, a re-encode, or most upload pipelines. A pixel watermark is the durable half of the pair.

Which is the fair reading of this teardown: the engineering is a reasonable response to a real regulatory obligation, and the disclosure has not caught up with the engineering. A transparency mechanism that is itself undisclosed is a slightly awkward place to end up.

What to take from this if you ship image generation

  • "Local" is a claim about compute, not about network. If any stage of your pipeline round trips, say so. Cocreator's inference genuinely runs on the NPU, and the feature still cannot start without a server call.
  • A GUID in the pixels plus a server record of the prompt is a join key. Microsoft has published nothing about how long promptGenerationId records are retained or who can query them. That is the unanswered question, not the watermark itself.
  • Decide fail-open versus fail-closed on purpose. Paint and Photos landed on opposite defaults with the same code. Yours should be a written decision, not an accident of which team wired it up.
  • Two layers beat one. If you need Article 50 compliance, plan for metadata plus a pixel or token mark, and assume the metadata will be stripped by ordinary user behavior.

Caveats

This is one researcher, one machine, and specific builds: Paint 11.2605.71.0 and Photos 2026.11060.2004.0. The findings have not been independently reproduced at scale in public, and as of publication Microsoft has not publicly addressed them. The pixel-count figure comes from a synthetic test image, not a survey of real generations. And the scope really is limited to AI-generated and AI-edited output: nothing in the teardown shows Paint watermarking a hand-drawn rectangle.

Key Takeaways

  • Paint's Cocreator sends your prompt to a Microsoft moderation endpoint before local generation, and the response returns a watermarkId GUID that gets embedded into your image.
  • The embedded payload is 18 bytes: header 0x4c, the 16-byte GUID, and a one-byte checksum, written by Watermarker.dll with a minimum image size of 192 by 192.
  • In a 512 by 512 test image, 193,376 of 262,144 pixels changed, at imperceptibility levels consistent with Microsoft's own InvisMark research.
  • The signed C2PA manifest records the same GUID as a com.microsoft.invismark.1 soft-binding, tying the metadata and the pixel mark to one server-side record.
  • Microsoft's Paint application card discloses C2PA credentials and cloud content filtering, but not the pixel watermark or the server origin of the identifier.
  • Paint aborts generation if watermarking fails; Photos ships the image unmarked. Same DLL, opposite defaults.

Sources: Xusheng Li, "Microsoft Paint and Photos Embed Server-Issued GUIDs as Invisible Watermarks in Locally-Generated Images", Microsoft Learn, Microsoft Paint application card, Microsoft Support, Use Copilot+ PC features in Paint, microsoft/InvisMark on GitHub, InvisMark (arXiv 2411.07795, WACV 2025), C2PA, EU AI Act Article 50, Hacker News discussion

AIMicrosoftWatermarkingC2PAProvenanceWindowsReverse EngineeringCreator Rights
CONSOLE
$