From 2c412b56c4fbb4855d037bdf390d1c7357f67066 Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Mon, 24 Aug 2026 20:03:29 -0700 Subject: [PATCH] Document SynthID GitHub sweep findings --- docs/module-internals.md | 3 + docs/synthid-classifiers.md | 372 +++++++++++++++++++++++++++++- docs/synthid-detector-research.md | 201 ++++++++++++---- docs/synthid-oracle-ladders.md | 17 +- docs/synthid-removal-research.md | 82 +++++-- 5 files changed, 612 insertions(+), 63 deletions(-) diff --git a/docs/module-internals.md b/docs/module-internals.md index 7c825be..30a4064 100644 --- a/docs/module-internals.md +++ b/docs/module-internals.md @@ -716,6 +716,9 @@ had AUC 0.473, and two prespecified amplitude-aware V4 rerankings reached only contribution is the solid-reference phase-consensus construction, not either published single-image threshold. Full methodology and the DALL-E reference-set confound are recorded in the detector research plan. +A later exact repeat on the hash-disjoint v7 challenge confirmed the same +failure: the published cut accepted 77/200 Google, 76/200 OpenAI, and 27/64 +personal cameras, for Google-versus-OpenAI/camera AUC 0.510. A direct exact-1024 reproduction of the same V4 artifact confirmed rather than rescued that verdict: the union of its two published profiles accepted 177 of 443 Google rows and 60 of 162 controls. The artifact's floor left only about two diff --git a/docs/synthid-classifiers.md b/docs/synthid-classifiers.md index 2e60ae7..beada75 100644 --- a/docs/synthid-classifiers.md +++ b/docs/synthid-classifiers.md @@ -77,9 +77,11 @@ error, not Gemini contamination. | --- | --- | --- | | Missing camera PRNU | Gray `gpt-image-2` highpass RMS 0.25 vs COCO 14.6 | Texture confound. A Wiener PRNU residual on *photographs* vs Model 1 errors is the real test | | JPEG ELA | COCO 3.13, s1 1.97, gray stamp 0.49 | Export history, leaks PNG vs JPEG, not a provider | -| CFA / Bayer presence | Untested as a *detector* | Camera photos demosaic; many generators do not. Inverse of the Bayer remover arm | -| Double-JPEG ghosts | Untested | ChatGPT download codec fingerprint, not a payload | -| Perfect-circle / text-edge rate | Untested | Graphics abstain for Model 1, not Gemini-vs-OpenAI | +| CFA / Bayer presence | Photo-edit ratio 0.117 vs camera 0.184 vs gray 0.588 | Weak camera vote, overlap. Inverse of the Bayer remover | +| Double-JPEG ghosts | s1 / gpt-image-2 / camera all min at Q90 | Codec, not a provider | +| Perfect-circle / text-edge rate | Circles/MP 385 vs 536, edge 0.052 vs 0.072 | Too noisy for abstain | +| Wiener PRNU on photographs | Edits 4.61 vs camera 8.05 | Donor JPEG texture leftover, not a missing sensor | +| PNG Paeth filter mix | gpt-image-2 PNG 99.9% Paeth vs camera 73% | Export fingerprint | None of these should be named a SynthID score. @@ -101,11 +103,11 @@ task, not a watermark task. Adjacent papers: | Ojha, Li, Lee, [arXiv:2302.10174](https://arxiv.org/abs/2302.10174) (CVPR 2023, UnivFD) | A classifier trained to see "fake" treats unseen generators as the real sink. Frozen CLIP + nearest neighbor / linear probe generalizes better than a trained CNN | This is the architecture. We finetuned the last two CLIP-L vision blocks instead of freezing, and put Firefly and a locked Open Images fresh set in the gate | | Cozzolino et al., [arXiv:2312.00195](https://arxiv.org/abs/2312.00195) | CLIP linear probe, few shots from one generator, holds on DALL-E 3 / Midjourney / Firefly | Firefly is the cell we required. Their paper is why Firefly belongs in the test, not as a surprise | | Corvi et al., [arXiv:2304.06408](https://arxiv.org/abs/2304.06408) | Spectral peaks and mid-high power differences, GAN and diffusion | Generator fingerprint, not a payload. Explains why a Fourier codebook lights up Google *and* Open Images | -| Zhong, Xu, Zou, [arXiv:2601.22778](https://arxiv.org/abs/2601.22778) (DCCT) | Self-supervised color-channel prediction under a Bayer mask; theoretical gap between photo CFA correlations and AIGC | The published "CFA as a camera vote". Untested here. Inverse of the Bayer remover arm | +| Zhong, Xu, Zou, [arXiv:2601.22778](https://arxiv.org/abs/2601.22778) (DCCT) | Self-supervised color-channel prediction under a Bayer mask; theoretical gap between photo CFA correlations and AIGC | Local Bayer interpolation-error ratio: edits 0.117 vs camera 0.184. Weak vote, not a payload | | Klier and Baier, DFRWS EU 2026 | AI noise is not predominantly additive. Standard PCE vs smartphone PRNU: FPR 61% Firefly Image 4, 100% ChatGPT 5. Center crop kills those false positives without hurting true camera matches | Do not call missing PRNU a SynthID score. If we ever add a Wiener residual, crop and a recorded PCE threshold come with it | | Popescu and Farid, IEEE Trans. Signal Process. 2005 | CFA interpolation leaves neighbor correlations; splicing breaks them | Classical forgery localization, not generation detection | | Wang, Wang, Zhang, Owens, Efros, [arXiv:1912.11035](https://arxiv.org/abs/1912.11035) (CVPR 2020, CNNDetect) | Classifier on ProGAN + JPEG/crop aug transfers to many CNNs | The "one generator is enough" claim. Ojha is the correction once diffusion exists | -| Wang et al., DIRE, [arXiv:2303.09295](https://arxiv.org/abs/2303.09295) (ICCV 2023) | Reconstruction error under a frozen diffusion model | Open Model 1 sibling. Needs a GPU diffusion pass per image. Not a watermark | +| Wang et al., DIRE, [arXiv:2303.09295](https://arxiv.org/abs/2303.09295) (ICCV 2023) | Reconstruction error under a frozen diffusion model | SDXL float32 at 512. VAE RMS: camera 11.84, photo edit 9.89, s1 9.15, gray stamp 1.24. DDIM DIRE RMS: camera 33.0, s1 31.5, photo 30.9, gray 2.40. Texture rank, not a payload. Float16 DDIM NaN'd on MPS | They do not substitute for `verify-openai-synthid`. @@ -115,9 +117,9 @@ documented Gemini repeating the first file's SynthID verdict inside a chat; Google said that was fixed 2026-07-16. The OpenAI provenance API is a different endpoint. -## Closed: provider names from pixels +## Provider names from pixels -After the keyless mark hunt closed, the remaining ask was: given a file +With the keyless mark hunt still open, the adjacent ask was: given a file with no metadata, is this OpenAI, Gemini, or not AI, with almost no errors on camera photographs. That is this section. It is not a SynthID detector. Firefly, PixelBin, and other generators have to sit in the @@ -137,6 +139,362 @@ a narrower train set (fresh FPR 2.1%, Firefly still 95%). `provider-report-clip-l-ft.json`, `provider-union-report.json`. +### Strict abstention does not recover provider identity + +An `unknown` class makes the claim narrower, but neither existing +representation has a useful high-precision operating point. A +leave-one-foreign-family-out ridge on the 124-d residual bank set each cut +above every calibration negative. Mean OpenAI recall fell to 1.3% and mean +Google recall to 4.4%, while a held-out foreign family was still attributed to +a provider up to 5.0% of the time and photographs were called OpenAI up to +0.52% of the time. + +The CLIP-L-ft head has the same failure at a 0.1% calibration-negative cut. +On 400 disjoint queries per provider, OpenAI recall was 1.0% and Google recall +was 0.5%. It still called 1/11 held-out FLUX images OpenAI and 1/750 COCO +photographs OpenAI. Zero calibration false positives reduced both provider +recalls to zero. These are abstaining content classifiers, not precise source +finders. + +A nonlinear head and local-neighbor decision do not expose a hidden provider +partition in the same embeddings. Across five balanced 768-128-3 MLP seeds, +strict test recall ranged from 0.5-7.0% for OpenAI and 0.75-1.0% for Google, +with 6-19 false attributions among 6,550 locked negatives. The best +calibration-selected `k=3` local-neighbor rule reached 0.5% OpenAI and 3.25% +Google recall and still called one TC260 image Google. + +### Pixel finetuning learns the train split, not an exact provider boundary + +The last two CLIP-L vision blocks were then finetuned directly for +`openai` / `google` / `unknown`: 9,063 fit images, 3,537 disjoint calibration +images, 400 balanced steps, and random JPEG 40-95, 85-100% crop, and mild blur. +Each provider cut was placed above every calibration negative. Calibration +recall was 4.3% OpenAI and 5.2% Google. + +The time-disjoint locked result was 6/400 OpenAI and 10/400 Google. One Google +image and one TC260 image were called OpenAI. All 500 unseen-AI controls and +all 4,945 locked photographs stayed `unknown`, including 3,000 fresh Open +Images, but that photo specificity does not repair an AI-source error. An +oracle cut above both locked OpenAI errors leaves only 1/400 OpenAI; it is an +upper bound, not a valid post-test threshold. The model is not shippable. + +The independent high-frequency route is already closed at the tested +capacity. A four-layer opponent-residual patch CNN reached AUC 0.44-0.56 +against foreign generators, reversed to 0.15 on a fresh era, and accepted +95-100% of several held-out Firefly, Microsoft, fal.ai, and PixelBin families +at its photo-median threshold. It learned AI rendering versus photography, +not vendor identity. + +### External surrogate and forensic-descriptor audit + +The public +[`newideas99/gpt-image-synthid-detector`](https://github.com/newideas99/gpt-image-synthid-detector/tree/5495e09) +does not supply a causal SynthID contrast. Its negatives are lightly +regenerated positive images, so the trained ResNet/EfficientNet ensemble can +read the regeneration pipeline. On a blind 517-file local pilot, OpenAI versus +all AUC was 0.630. At the repository's 0.5 cut it retained 92/100 OpenAI and +accepted 307/417 negatives, including 104/120 Open Images, 26/30 COCO, 34/50 +Google, and 8/10 Firefly. A later exact repeat on the hash-disjoint v7 challenge +retained 172/200 OpenAI but accepted 110/200 Google and 53/64 personal camera +photos. OpenAI-versus-camera AUC was 0.549. Even a post-test cut above every +camera retained only 14/200 OpenAI and still accepted 4/200 Google; that is an +upper bound, not a deployable threshold. Replaying the v11 rule on the same +rows showed no hybrid value: using that camera-safe post-test cut on `unknown` +rows rescued zero v11 OpenAI misses and introduced two Google-to-OpenAI errors. +Allowing it to override the Gemini branch still corrected zero OpenAI files +and introduced four Google-to-OpenAI errors. It is a visual-domain classifier, +not an independent confirmation signal. + +The current [`aloshdenny/reverse-SynthID`](https://github.com/aloshdenny/reverse-SynthID/tree/b110836) +V4 codebook also adds no useful hybrid evidence. A pickle-free exact inference +repeat on v7 accepted 77/200 Google, 76/200 OpenAI, and 27/64 personal camera +files at its published 0.52 threshold. Google-versus-OpenAI/camera AUC was +0.510. Applied only to v11 `unknown` rows, that threshold would rescue 26 +Google files while adding 2 OpenAI and 27 camera errors. A post-test cut above +every OpenAI and camera retained one additional Google file; 0.5% recall chosen +after opening the test is an upper bound, not a rule. The older V3 published +cut would add two v11 Google misses and no v7 errors, but it previously accepted +5/499 controls and 6/1,000 fresh Open Images. A 1%-recall OR rule with that +measured false-positive history is also rejected. + +The public [`Ristellise/REGRET`](https://github.com/Ristellise/REGRET/tree/7d449034bf323987e7e608e7886e029ed20fd847) +SPAM model is another forensic descriptor, not a decoder. The audited pickle +contained only an sklearn pipeline, scaler, logistic regression, and numeric +numpy globals; inference used an exact restricted allowlist. At the published +0.5 cut it accepted 139/200 Google, 141/200 OpenAI, and 36/64 personal cameras. +Google-versus-camera AUC was 0.647 and OpenAI-versus-camera AUC was 0.614. A +post-test cut above those 64 cameras appeared to retain 22 Google and 2 OpenAI, +but a frozen extension rejected the tail: it accepted 47/500 new personal +cameras, 39/600 other photos, 10/75 BigGAN, 3/75 Midjourney, 14/75 SDXL, and +5/75 VQDM. Target-versus-all-controls AUC was 0.709. It adds no safe v11 rescue. + +[`vordme2010/synthid-dataset`](https://github.com/vordme2010/synthid-dataset/tree/133a27088f6f4d695c79db9a1a70fa8e7fa3adad) +publishes a useful flat-field corpus but an invalid open-world classifier +contrast. Its Tier-1 matrix has 500 Gemini-flat positives and 1,500 synthetic, +spectrum-matched, or phase-scrambled negatives, with no real negative. The +33 features include noise scale and radial power as well as six hand-selected +carrier bins. Rebuilding the repository's seed-42 RBF SVM from the safe numeric +matrix, without loading joblib, accepted 1/200 current Google, 0/200 OpenAI, and +0/64 personal cameras on v7. Google-versus-camera AUC was 0.503 and the other +two AUCs were 0.497-0.504. The reported AUC above 0.999 measures the synthetic +negative recipe and flat renderer epoch; it cannot confirm the current source +finder or a SynthID payload. + +[Forensic Self-Descriptions](https://github.com/ductai199x/Forensic-Self-Descriptions-CVPR25/tree/50f2eae) +(CVPR 2025) is a genuinely different representation: constrained prediction +residuals are summarized as a 960-d forensic descriptor. Its ready attribution +head is not usable here. Three current OpenAI files were all called `Real`, +while one Microsoft file was called `GPT-Image 1/1.5` at confidence 0.863. + +A custom source head on a native 256-pixel center crop was more informative. +PCA-64 plus logistic regression, with each provider cut above every calibration +negative, gave OpenAI AUC 0.872 and 3/50 strict OpenAI recall with 0/388 test +false attributions. Its Google head failed on Bytedance, Canva, FLUX, +Microsoft, and an Open Images photograph. On a later unused-hash challenge the +OpenAI FSD head alone accepted 14/300 OpenAI, 3/300 TC260, and 3/90 PixelBin. +FSD is therefore an independent source cue, not a sufficient classifier and +not a watermark statistic. + +### Rejected narrow two-signal cascades, 2026-08-23 + +The visible Gemini sparkle is absent from the target generation and is not a +feature or a gate. Two metadata-free intersections did survive a new challenge: + +| Cascade | Development | Unused-hash challenge | +| --- | --- | --- | +| Google provider probability >= 0.8876249 **and** registered-v3 lattice >= 1.0 | 3/45 Google, 0/30 lattice-positive foreign files | 3/300 Google, 0/690 OpenAI/TC260/PixelBin | +| OpenAI provider probability >= 0.8822824 **and** FSD probability >= 0.9912320 | The two cuts were frozen independently | 3/300 OpenAI, 0/690 Google/TC260/PixelBin, 0/500 photographs | + +The Google result is a low-recall intersection of a content head and an +origin-locked renderer lattice. A two-pixel crop destroys the lattice, so an +indeterminate result says nothing about SynthID. It is evidence for a narrow +Gemini/Imagen pipeline, not a public decoder. + +All three OpenAI challenge positives were 1086x1448 RGB PNGs, the measured +ChatGPT export geometry. Thirty known non-OpenAI files at exactly 1086x1448 +(TC260, Apple, Microsoft, Canva, Firefly, Google, and others) produced zero +first-gate positives. A scan of 1,194 unique files at that geometry with no +provider or platform label produced 29 pixel-gate candidates and four final +hybrid candidates. Three had only PNG image-data chunks; the fourth carried +generic DPI/orientation fields but no provider or provenance label. Visual +inspection found four plausible AI generations. They remain candidates, not +ground truth, until a held-out oracle or original source confirms them. + +The full luma 16-32-pixel phase-ring head is not a third confirmation. It +rejected all three known and all four unlabeled OpenAI hybrid candidates while +accepting 3/30 known non-OpenAI same-geometry controls. Its global test AUC was +0.600 for OpenAI and it stays closed. + +These cascades established that independent intersections could suppress the +observed false positives, but about 1% recall is not useful for the source-hunt +task. They are rejected as operating detectors. The FSD implementation and +weights are also research-only under CC BY-NC-SA 4.0. + +Local artifacts: `lattice-pixel-hybrid-challenge.json`, +`fsd-openai-challenge-report.json`, +`unlabeled-1086x1448-openai-hybrid-candidates.json`. The research entry point +is `.local-eval/synthid/ai-photo-2026-08-22/hybrid_source_finder.py`. + +### Canonical forensic source finder, 2026-08-23 + +An overlooked pixel representation materially improves the strict result. It +normalizes each file to 512x512, then extracts 1,794 metadata-free features +from opponent-color residuals: patch power and variation, phase coherence, +autocorrelation, low-bit correlations, and residual-error histograms. The +OpenAI branch intersects its canonical forensic score with a weak provider +pixel vote. The Gemini branch intersects a forensic/provider fusion with the +registered-v3 lattice. The visible Gemini sparkle remains excluded. + +The single-scale cuts were frozen before a third hash-disjoint challenge. The +result was: + +| Challenge cell | OpenAI candidate | Gemini candidate | Any candidate | +| --- | ---: | ---: | ---: | +| OpenAI | 51/300 | 1/300 | 52/300 (17.3%) | +| Google | 0/300 | 34/300 | 34/300 (11.3%) | +| Open Images photographs | 1/1,000 | 0/1,000 | 1/1,000 (0.1%) | +| TC260 | 0/7 | 0/7 | 0/7 | + +For the requested union, 86/600 OpenAI-or-Google targets were found, 14.3% +recall instead of the rejected cascades' 1%. One OpenAI file crossed through +the Gemini branch, and one known photograph crossed through the OpenAI branch. +The seven remaining unused TC260 files are too few to establish specificity, +and no fresh PixelBin, Firefly, Microsoft, or other generator hashes remained +outside the earlier model and challenge manifests. + +This v3 result established a strict source-candidate finder, not an exact +identifier or a SynthID decoder. It does not recover a payload, and an +`unknown` result says nothing about whether SynthID is present. + +Local artifacts: `source-finder-v3-selection.json`, +`source-finder-v3-challenge.json`, `google-canonical-forensic.json`, and +`google-forensic-pixel-fusion.json`. The same local research entry point now +implements this rule without the FSD dependency. + +### Multiscale strict finder, 2026-08-24 + +The 512x512 normalization was discarding usable scale-specific evidence. A +frozen union now takes the strongest OpenAI forensic response over 512, 640, +768, and native views, gated by the provider pixel head. The Google branch +takes the strongest forensic/provider fusion over 384, 512, 640, 768, and +native views, then requires the same registered-v3 lattice. Development on +the second and third challenges found 539/1,200 targets and 0/1,657 +photograph/TC260 controls. + +The views and cuts were written before opening a fourth challenge whose hashes +were disjoint from every model manifest and the first three challenges: + +| Challenge cell | OpenAI candidate | Gemini candidate | Any candidate | +| --- | ---: | ---: | ---: | +| OpenAI | 92/300 | 11/300 | 103/300 (34.3%) | +| Google | 0/300 | 173/300 | 173/300 (57.7%) | +| Open Images photographs | 0/1,000 | 0/1,000 | 0/1,000 | +| TC260 | 1/25 | 0/25 | 1/25 | + +For the requested union, the blind result is 276/600, 46.0% recall, with +1/1,025 non-target candidates. This is 3.2 times the single-scale v3 recall +and 46 times the rejected 1% cascades. The one false candidate is TC260, not a +camera photograph. Eleven OpenAI files crossed through the Gemini branch; +that is a provider-attribution error but still a correct hit for the declared +OpenAI-or-Google union. + +This remains a source-candidate finder, not an exact identifier or a SynthID +decoder. Fresh unused paths from the other generator families were not +available for v4, so the 0.1% observed non-target rate is not an open-world +precision claim. Robustness to crop, resize, re-encoding, and screenshot +capture is also not established. Keep the models and paths in `.local-eval`; +do not add a runtime or public CLI until a new temporal challenge with fresh +foreign-generator families establishes positive precision. + +Local artifacts: `source-finder-v4-selection.json`, +`source-finder-v4-rule.json`, `source-finder-v4-challenge.json`, and +`multiscale-forensic-development.json`. The local research entry point +implements the frozen multiscale rule and still uses no metadata or visible +sparkle. + +A post-hoc OR over every per-view zero-development-error OpenAI cut is +rejected. It raised v4 OpenAI recall to 153/300 but also accepted 6/1,000 +photographs and 3/25 TC260 controls. The apparent union of many individually +strict cuts was multiple-testing overfit, not additional independent evidence. + +### Original-export hybrids, 2026-08-24 + +Three more hash-disjoint challenges tested whether multiscale fusion could be +made useful without metadata. The v5 ExtraTrees union improved exact provider +recall to 363/600 (60.5%) and provider-union recall to 373/600 (62.2%), but it +also accepted 8/1,000 photograph and foreign-generator controls. A revised +Google confirmation removed those eight development errors. Adding an +AI-versus-camera gate in v6 did not transfer: exact recall fell to 327/600 +(54.5%), union recall was 341/600 (56.8%), and 2/500 previously unseen personal +camera photographs were called OpenAI. + +The two camera errors exposed a stronger but narrower signal. Current OpenAI +exports in these sets are PNGs produced with adaptive scanline filters. The +camera errors were JPEGs, while the earlier TC260 error was a PNG encoded with +filter zero on every row. A strict PNG parser now requires a non-interlaced PNG +with at least one adaptive filter before the OpenAI branch can emit a result. +This reads the image container and pixels, not EXIF, C2PA, a filename, or a +visible label. It also changes the claim: a re-encoded OpenAI JPEG must abstain. + +The complete frozen v7 rule reached 215/400 exact provider matches (53.8%) and +221/400 provider-union matches (55.3%) on a new challenge, with 0/64 new camera +controls. Its cells were 114/200 exact OpenAI and 101/200 exact Google. The PNG +gate repaired the observed specificity problem, but the old OpenAI forensic +head remained the recall bottleneck. + +A subsequent v8 development hybrid trains an ExtraTrees OpenAI head on v4-v5 +multiscale forensic scores, pixel probabilities, and PNG encoding structure. +Model selection used v6. The final 0.47 precision cut was chosen after v7 and a +known-origin local subset had been opened, so the following is a transfer +measurement, not another blind result: + +| v7 cell under v8 development rule | OpenAI | Gemini | Unknown | +| --- | ---: | ---: | ---: | +| OpenAI | 190/200 | 3/200 | 7/200 | +| Google | 0/200 | 102/200 | 98/200 | +| Personal camera photographs | 0/64 | 0/64 | 64/64 | + +That is 292/400 exact provider matches (73.0%) and 295/400 provider-union +matches (73.8%). On a metadata-free scan of 12,775 readable unique local files, +the precision rule emitted 131 OpenAI and 17 Gemini candidates. Filenames were +not model inputs. They were used only after scoring to audit a known-origin +development subset: 45/53 OpenAI and 16/29 Gemini were found, with no cross- +provider errors at the selected cut. + +The remaining Google miss set contained two different export pipelines: PNG +and JPEG. A second development branch parses only JPEG codestream parameters, +including quantization tables, chroma sampling, and progressive encoding; it +explicitly skips APP0-APP15 and COM segments. Training one Google model per +encoding class on v4 and selecting zero-validation-error cuts on v5-v6 raised +the v11 transfer result to: + +| v7 cell under v11 development rule | OpenAI | Gemini | Unknown | +| --- | ---: | ---: | ---: | +| OpenAI | 190/200 | 4/200 | 6/200 | +| Google | 0/200 | 126/200 | 74/200 | +| Personal camera photographs | 0/64 | 0/64 | 64/64 | + +This is 316/400 exact provider matches (79.0%) and 320/400 provider-union +matches (80.0%). A separate 500-file personal-camera slice, unused by v4-v7 +model or threshold selection, produced zero Google candidates. On the local +12,775-file scan, v11 emitted the same 131 OpenAI candidates and 106 Gemini +candidates. The known-origin audit did not improve beyond 45/53 OpenAI and +16/29 Gemini, so the extra 89 Gemini results remain unlabeled recall-mode +candidates rather than confirmed finds. + +This is the best local source finder in the campaign, but it is still not a +SynthID detector, payload decoder, or open-world precision proof. The v8 rule +is post-hoc, and candidates outside the known-origin audit are not ground +truth. The OpenAI branch is intentionally scoped to original-style PNG +exports. The v8 148-candidate result is the precision mode; the v11 +237-candidate result is a broader recall mode whose additional local results +lack ground truth. A new temporal blind challenge with new foreign generators +and PNG camera/editor controls is required before a runtime or public CLI is +justified. + +Local artifacts: `source-finder-v7-selection.json`, +`source-finder-v7-challenge.json`, `source-finder-v8-rule.json`, +`source-finder-v8-openai-extra-trees.joblib`, and +`source-finder-v11-google-per-codec.joblib`. Private scan reports, paths, +labels, and image files remain outside the repository. + +### Published few-shot attribution also fails the open-world gate + +[OmniDFA](https://arxiv.org/abs/2509.25682) is a purpose-built few-shot source +attributor rather than a generic content embedding. Its published `part1` +checkpoint is the correct unseen-generator fold for DALL-E 2 and DALL-E 3: +those generators are in `part1` validation and absent from its training list. +The same checkpoint has seen Imagen, so its Google result is not a clean +unseen-Imagen benchmark; the OpenAI result is sufficient to reject the shared +runtime. + +With 20 support images per provider and provider-specific similarity plus +margin cuts calibrated to zero false attributions over 160 negatives, a +content-hash-disjoint 745-image evaluation produced: + +| Cell | Result | +| --- | ---: | +| OpenAI recall | 9/50 (18%) | +| Google recall | 4/50 (8%) | +| Microsoft called OpenAI | 3/15 (20%) | +| Kodak called OpenAI | 3/24 (12.5%) | +| Canva called Google | 1/15 (6.7%) | +| fal.ai called OpenAI | 1/15 (6.7%) | +| xAI called OpenAI | 1/15 (6.7%) | +| unseen Higgsfield called OpenAI | 1/11 (9.1%) | +| fresh Open Images / COCO false attributions | 0/100 / 0/50 | + +Provider multimodality is not the missing fix. Choosing 1-10 spherical +prototypes only by calibration recall selected five: test recall fell to 16% +OpenAI and 4% Google, while false attributions remained on Firefly (2/15), +Kodak (2/24), Microsoft, ByteDance, TC260, and Made-with-AI samples. + +Native files already fail, so JPEG, resize, crop, and screenshot variants were +not run for OmniDFA. Do not add a provider-attribution runtime or CLI from that +model. General exact OpenAI/Gemini identification remains unsupported. The +strict source finder above emits candidates; it does not read the SynthID +payload. + ### 124-d lattice as pipeline ID, not a vendor CLIP head Provider-class ridge on 124 native residual features (70/30 once, not a diff --git a/docs/synthid-detector-research.md b/docs/synthid-detector-research.md index 20db417..2097233 100644 --- a/docs/synthid-detector-research.md +++ b/docs/synthid-detector-research.md @@ -12,8 +12,11 @@ ## Result -The local OpenAI SynthID detector hunt closed 2026-08-20. Google has no -public payload decoder. Nothing in this project reproduces one. +The hunt for a local, keyless OpenAI SynthID pixel detector is open. +Google has no public payload decoder, and nothing in this project +reproduces one. Closed routes below failed to read the official oracle +contrast on photographs. The remaining work is a new waveform, a new +pair mint, or a new statistic, not a rerun of those routes. The mark behaves like a keyed spread-spectrum residual: a content-adaptive `x' = x + g(x)` with a paired decoder (DeepMind patent family, optional @@ -43,13 +46,68 @@ What the product uses for the *watermark* is signed provenance and Lineage measurements of that expert are in [classifier models](synthid-classifiers.md). +## Public GitHub sweep, 2026-08-24 + +GitHub's primary-repository search returned 78 repositories with `synthid` in +the name and 81 with it in the description, 133 unique repositories in total. +The fork-inclusive searches were much larger and capped or dominated by copies +(860 name hits and 1,311 description hits), so this is not a claim that every +fork or unindexed private repository was read. The sweep also used targeted +code searches for detector, verifier, correlation, codebook, bypass, and +removal implementations. SynthID-Text, visible-corner-mark removers, metadata +cleaners, wrappers, and literal ports were classified before inspecting the +remaining image-pixel candidates at pinned commits. + +The audits are not null results. They separate three claims that must not be +collapsed: a repeatable image statistic exists, that statistic is a calibrated +single-image SynthID detector, and changing its score transfers to the +provider's production decoder. The repositories support parts of the first +claim. None supports the second or third on the current challenge data. + +| Repository | Retained contribution | Rejected use | Decisive result | +| --- | --- | --- | --- | +| [`Rinne414/SynthID-detector`](https://github.com/Rinne414/SynthID-detector/tree/b08abff06b67c37db9dfa7c6ed63760a446d560f) | A reproducible fixed-residual correlator and a useful spoofability negative control | Current-image detector or fixed-template remover | All three templates detected 0/464 current OpenAI, Google, and camera files. Adding the expected template spoofed the public detector, while subtracting 0.25-2x from an official positive left SynthID `detected` down to 25.72 dB | +| [`newideas99/gpt-image-synthid-detector`](https://github.com/newideas99/gpt-image-synthid-detector/tree/5495e09c62dc26112f9a0e6cfab469f9a10f37e3) | Evidence that a CNN can learn a renderer/regeneration-domain signature, plus a white-box shortcut baseline | Payload decoder, independent hybrid confirmation, or removal oracle | The published cut accepted 53/64 personal cameras and gave OpenAI-versus-camera AUC 0.549. A gradient drove the surrogate effectively to zero, but official SynthID stayed `detected` through +/-8/255 at 34.30 dB | +| [`aloshdenny/reverse-SynthID`](https://github.com/aloshdenny/reverse-SynthID/tree/b11083676fd3ee3ff97ce9d03c0e409e46905902) | Cross-color phase consensus and further evidence for a repeating Google renderer-lineage pattern | The published V3/V4 thresholds as presence detectors, or Round-06 as a verified quiet remover | V4 accepted 77/200 Google, 76/200 OpenAI, and 27/64 cameras, AUC 0.510. Round-06 has no published per-image oracle evidence and uses regeneration/distortion with 14/11 dB PSNR floors | +| [`Ristellise/REGRET`](https://github.com/Ristellise/REGRET/tree/7d449034bf323987e7e608e7886e029ed20fd847) | A compact 147-d second-order SPAM descriptor and a safely auditable sklearn model | Google or OpenAI detector, or a high-precision hybrid rescue | The published cut accepted 139/200 Google, 141/200 OpenAI, and 36/64 cameras. A camera-safe post-test cut looked promising on v7 but then accepted 47/500 new cameras, 39/600 other photos, and 32/400 foreign-AI controls | +| [`vordme2010/synthid-dataset`](https://github.com/vordme2010/synthid-dataset/tree/133a27088f6f4d695c79db9a1a70fa8e7fa3adad) | A public 2026 Gemini flat-field corpus, safe numeric features, and explicit candidate carrier bins | Its reported near-perfect Tier-1 AUC as open-world SynthID evidence | Training used 500 Gemini flats against 1,500 synthetic or phase-scrambled negatives and zero real photographs. Rebuilding the SVM from the safe matrix accepted 1/200 Google, 0/200 OpenAI, and 0/64 cameras on v7; Google-versus-camera AUC was 0.503 | + +Useful forensic signal is therefore not synonymous with a production +watermark decoder. The Google lattice idea is retained only as a +research-lineage component; it cannot be labelled SynthID. The fixed template +and CNN gradient are retained as negative controls. None of these public +implementations is shipped as a detector or remover. Detailed classifier and +attack measurements live in [classifier models](synthid-classifiers.md) and +[mark removal](synthid-removal-research.md). + +### Google verifier surfaces found in the sweep + +Two real but non-local verifier paths surfaced. The historical Vertex SDK +exposed `WatermarkVerificationModel.from_pretrained("imageverification@001")`. +The class still exists in `google-cloud-aiplatform` 1.165.1, but warns that it +was deprecated 2025-06-24 with removal scheduled for 2026-06-24. Calls in two +projects with Vertex enabled now reject the publisher model id as invalid. A +repository using `response.watermark_detected` is also stale: the actual SDK +property was `watermark_verification_result`, backed by the prediction's +`decision` field. + +A newer unlisted upload route, +`POST https://synthid.googleapis.com/upload/v1:verifyContent`, is live enough +to identify itself as the SynthID API and return `SERVICE_DISABLED` for a real +public image. It has no public discovery document, did not appear in the +project's available-services listing, and no authorized successful response +was obtained. Enabling a cloud service was deliberately not attempted. This +may be an access-gated research oracle, but it is not a local decoder and does +not satisfy the metadata-free offline product requirement. Gemini chat remains +the only Google verifier actually evidenced by the public bypass corpora. + ## Closed detector routes | Route | Close | Why | | --- | --- | --- | | Wavelets / FFT / cepstrum as a single-image detector | 2026-08-09 | TrustMark proxy: 318-d wavelet/spectral summary AUC 0.653 and 0 TPR at a clean calibration cut. Complex FFT maps AUC 0.516. Spatial RGB still won | -| `aloshdenny/reverse-SynthID` V3 phase codebook | 2026-08-09 | Pickle-free numeric audit. 5/5 Google positives, 0/194 then-available negatives. Discovery only: not 0.1% FPR, no same-provider hard negatives | -| `aloshdenny/reverse-SynthID` V4 | 2026-08-13 | Commit `b110836`. Better-of-two profiles: 141/355 Google positives and 191/499 controls. Frozen 1,000 Open Images: 386 accepted. Paired AUC 0.517. Threshold sits 0.02 above chance phase similarity | +| `aloshdenny/reverse-SynthID` V3 phase codebook | 2026-08-09/24 | Pickle-free numeric audit. The original pilot was 5/5 Google positives and 0/194 then-available negatives. The broader audit was 5/355 Google, 5/499 controls, and 6/1,000 fresh Open Images. On v7 it accepted 4/200 Google, 1/200 OpenAI, and 0/64 cameras; AUC 0.509. As a v11 `unknown` rescue it adds 2/200 Google on this test, but the historical control errors reject a 1%-recall OR rule | +| `aloshdenny/reverse-SynthID` V4 | 2026-08-13/24 | Commit `b110836`. Better-of-two profiles: 141/355 Google positives and 191/499 controls. Frozen 1,000 Open Images: 386 accepted. Paired AUC 0.517. An exact repeat on the hash-disjoint v7 challenge accepted 77/200 Google, 76/200 OpenAI, and 27/64 personal cameras; Google-versus-OpenAI/camera AUC was 0.510. Strict GUI aspect routing reduced support but not false acceptance. The threshold sits 0.02 above chance phase similarity | | `cebeuq/Synthid-Bypass` as a local decoder | 2026-08-13 | 12 public before/after diffusion pairs. Fixed carrier 10/12 before, 0/12 after. Gemini Verify still saw SynthID on two `before` files the carrier missed. Reconstruction removal, not a payload read | | S4: one content-independent pattern for both providers | 2026-08-15 | Google has a shared phase-coherent tile. OpenAI is at chance. See Result | | M2: mint Google encoder-off pairs | 2026-08-15 | No current Google path emits an unwatermarked image. See Result | @@ -73,6 +131,29 @@ Lineage measurements of that expert are in | Length-255 m-sequence vs 16x16 fold | 2026-08-23 | Max abs corr 0.059. Chance for n=255 is `1/sqrt(255) ≈ 0.063` | | Row-as-audio pitch peak | 2026-08-23 | Peak-to-mean 51 on flats, 46 on COCO noise residuals. Shared FFT peakiness, not a pitch | | 16x16 origin search of the flat 16-32 template on photos | 2026-08-23 | Zero-shift NCC 0.006-0.024, best of 256 shifts 0.013-0.026. Origin is not hiding a lock | +| Affine search of the 16-32 residual vs the flat template | 2026-08-23 | 11 `gpt-image-2` photos: zero-deg median 0.009, best rotation in ±4° 0.020, lift 0.011. Six COCO noise residuals: lift 0.008. Flats already peak at 0°. No hidden rotation or 3% scale lock | +| Fourier-angle scramble of 16-32 (true `(r, θ)` of the annulus) | 2026-08-23 | s1 24.1 dB official `not_detected`, cartesian replicate 24.8 dB `not_detected`. Decoder reads phase in that annulus, including angular organization. Not quieter than scramble | +| Baker-map of the 16-32 band | 2026-08-23 | s1 27.8 dB still `detected` | +| Poisson / photon-shot embedding | 2026-08-23 | Flat Anscombe LOO 0.7518 vs linear 0.7519. s1 Poisson 30.7 dB still `detected` | +| Nested LSB plus SynthID | 2026-08-23 | s1 55.9 dB still `detected`. Extra open stego does not hide or replace the mark | +| ICC sRGB rewrite | 2026-08-23 | No-op, PSNR inf. Mark is not in a profile that a pixel-preserving assign changes | +| Seam carve 8 columns of 16-32 energy | 2026-08-23 | s1 27.7 dB still `detected` | +| Extra OpenAI image ids as a new ensemble | 2026-08-23 | `gpt-image-1.5` and `gpt-image-1-mini` are encoder-off: C2PA `created, converted`, official `not_detected`, 16-32 corr vs the `gpt-image-2` gray stamp 0.003. Dated `gpt-image-2-2026-04-21` is the same family: C2PA `watermarked.unbound`, 16-32 corr 0.189. `chatgpt-image-latest` generate stays 403 until org verification | +| DIRE reconstruction error as a payload | 2026-08-23 | SDXL float32, 512 px. VAE RMS: gray 1.24, s1 9.15, photo edit 9.89, camera 11.84. DDIM DIRE RMS: gray 2.40, photo 30.9, s1 31.5, camera 33.0. Rank follows texture. Float16 DDIM NaN'd on MPS. Not a payload | +| HEIF / AV1 as a hidden carrier | 2026-08-23 | s1 HEIF q80 46.3 dB, q50 39.3 dB, AV1 CRF 32 37.2 dB, all official `detected`. Codec round-trip does not mint a new statistic | +| Print-scan simulation as the kill | 2026-08-23 | s1 24.95 dB still `detected`. Same PSNR class as 16-32 scramble, which kills. Generic 25 dB is not the mark | +| Mellin / log-polar \|F\| of the 16-32 residual | 2026-08-23 | Flat LOO 0.996-1.000, photo 0.996, COCO 0.991-0.995. The annulus envelope, not a payload. Scale chirps `r^{iα}`: flat 0.51, photo -0.27, COCO -0.58. No photo lock | +| Zernike n≤6 and PCET of the residual | 2026-08-23 | Flat LOO 0.77 / 0.75, same order as cartesian 16-32. Photo -0.007 / 0.044. COCO 0.23 / 0.35, above photos. Moments of the flat stamp, not a photograph decoder | +| Fresnel quadratic-phase of 16-32 (z=8,16,32,64) | 2026-08-23 | Flat LOO 0.750-0.753, photo 0.012, COCO -0.006. Unitary copy of the cartesian residual. No new shell | +| 8-bin Fourier orientation energy | 2026-08-23 | 0.999 flat, 0.966 photo, 0.995 COCO. Saturates | +| Chroma 16-32 as the payload | 2026-08-23 | Gray-flat Y LOO 0.682, Cb 0.064, Cr 0.025. s1 Y scramble 24.6 dB `not_detected`; Cb 45.0 dB and Cr 43.9 dB stay `detected`. Mark is in luma | +| One 90° Fourier sector of 16-32 | 2026-08-23 | s1 27.5 dB still `detected`. Decoder needs the whole annulus, not one wedge | +| Radial-phase-only scramble of 16-32 | 2026-08-23 | s1 25.0 dB `not_detected`. Phase as a function of radius, over the full ring, is enough to kill. Combined with Fourier-angle scramble, either polar coordinate of the annulus phase is a kill if the whole ring is hit | +| [`Rinne414/SynthID-detector`](https://github.com/Rinne414/SynthID-detector/tree/b08abff06b67c37db9dfa7c6ed63760a446d560f) fixed residual template | 2026-08-23/24 | The repository reports 0/33 held-out AI images and identifies its original result as self-correlation. Its pinned pre-May GPT-Image2 template first detected 0/11 current source-matched edits and 0/11 COCO sources. An exact repeat on a new 200 OpenAI / 200 Google / 64 camera challenge produced 0/464 detections for all three published templates at the 0.08 cut; maximum GPT-Image2 score on OpenAI was 0.0167. Adding 0.25x of that template to ten camera photos nevertheless spoofed 8/10 at median 43.5 dB, and 0.5x spoofed 10/10 at 37.4 dB. It is easy to inject the detector's expected answer, but the template is not present in held-out content. Independent repeat of the rejected fixed-template route, not a payload decoder | +| [`newideas99/gpt-image-synthid-detector`](https://github.com/newideas99/gpt-image-synthid-detector/tree/5495e09) CNN ensemble | 2026-08-24 | Exact frozen inference on 200 OpenAI, 200 Google, and 64 personal camera files: 172, 110, and 53 positives at the published 0.5 cut. OpenAI-versus-camera AUC 0.549. The training negatives are regenerated positives, while its confound probe transforms only positives and has no foreign-image control. A full-frame white-box attack drove its probability from 0.99995 to 0.25956 at ±2/255 and effectively zero at ±4/255, but the official OpenAI decoder stayed `detected` through ±8/255. Renderer/confound classifier, not a mark decoder | +| [`Ristellise/REGRET`](https://github.com/Ristellise/REGRET/tree/7d449034bf323987e7e608e7886e029ed20fd847) SPAM model | 2026-08-24 | Exact model inference on v7 gave Google-versus-camera AUC 0.647 but accepted 36/64 cameras at the published cut. A threshold chosen above those 64 cameras retained 22 Google and 2 OpenAI, then failed a frozen broader audit: 47/500 new personal cameras, 39/600 other photos, and 32/400 foreign generators crossed it. The apparent high-precision tail was a small-control calibration artifact | +| [`vordme2010/synthid-dataset`](https://github.com/vordme2010/synthid-dataset/tree/133a27088f6f4d695c79db9a1a70fa8e7fa3adad) Tier-1 SVM | 2026-08-24 | Rebuilt without loading joblib, using the repository's 2,000x33 numeric matrix, reference phases, noise template, seed-42 split, scaler, and RBF SVM. It accepted 1/200 current Google and no OpenAI/camera rows; all three AUCs were 0.497-0.504. Its published AUC above 0.999 distinguishes Gemini flats from generated derivatives, not current photographs | +| Generic GitHub heuristics and literal ports | 2026-08-24 | `hackerfactor/reverse-SynthID-C`, `BIRSAx2/ripmark`, and `xiaoyao9184/reverse-from-synthid` reproduce or wrap the already-rejected reverse-SynthID codebook. `AI-SCERN` uses uncalibrated annular energy, decoder-grid, and FFT-symmetry heuristics with no weights or held-out corpus. LSB flips, ±1 dither, and 100.5% resize tools publish no matching-oracle evidence. None adds an independent signal | ## Information budget on photographs (2026-08-21) @@ -228,10 +309,10 @@ emits an image whose latents already encode the message. | Source | Cue | Map | | --- | --- | --- | | Krawetz, "A Picture's Worth", 2007 (ELA) | Re-JPEG at lower quality, subtract | Already measured: COCO 3.13, s1 1.97, gray stamp 0.49. Codec history, not a payload. Farid publicly called ELA as likely to mislabel originals as it is to catch edits | -| Farid, IEEE TIFS 2009, JPEG ghosts | Difference energy vs a sweep of JPEG qualities; spliced regions ghost at their original Q | Untested here. The remaining JPEG check after ELA. Only defined on quantized JPEG | +| Farid, IEEE TIFS 2009, JPEG ghosts | Difference energy vs a sweep of JPEG qualities; spliced regions ghost at their original Q | Local: s1, a `gpt-image-2` photo, and a camera JPEG all minimize at Q90. Codec, not a payload | | Popescu and Farid, TR2004-515 | Copy-move via duplicated regions | Not generation, not a watermark | | Popescu and Farid, IEEE TSP 2005 | Resampling periodic correlations | Affine search cousin. A rotated SynthID residual is a different question | -| Wang et al., DIRE, [arXiv:2303.09295](https://arxiv.org/abs/2303.09295) (ICCV 2023) | Diffusion reconstruction error: generated images reconstruct, cameras do not | Model 1 sibling, needs a diffusion model. Inverse of our VAE round-trip: there the mark survived 22.3 dB; here the *error map* is the feature | +| Wang et al., DIRE, [arXiv:2303.09295](https://arxiv.org/abs/2303.09295) (ICCV 2023) | Diffusion reconstruction error: generated images reconstruct, cameras do not | Model 1 sibling. SDXL float32 at 512: DIRE RMS camera 33.0, s1 31.5, photo edit 30.9, gray stamp 2.40. Texture rank, not a payload. Inverse of the foreign-VAE remover: there the mark survived 22.3 dB | | Wang, Wang, Zhang, Owens, Efros, [arXiv:1912.11035](https://arxiv.org/abs/1912.11035) (CVPR 2020, CNNDetect) | One ProGAN classifier, heavy JPEG/crop aug, transfers to many CNNs | Ancestor of "train on one generator". Ojha showed the sink-class failure once diffusion arrived. We required Firefly for that reason | C2PA is the non-pixel stack: a signed manifest, stripped by @@ -267,15 +348,19 @@ Gabor packet is the same sinusoid windowed in space. | Circular chirp (SPIE 6072, 2006) | Polar map of a 1-D chirp onto a ring | JPEG (tune chirp rate) plus rotation (the ring) | | Tree-Ring (Wen 2023) | Concentric rings in the *latent* Fourier plane | Crop/flip by construction. Not a pixel wave | -Our prepared polar 16-32 scramble is the attack on this family: keep -the Cartesian octave energy, randomize angle. If the official decoder -still reads `detected`, the OpenAI mark is not a polar harmonic. If it -flips near 25.6 dB, angular structure mattered. +The 2026-08-23 file named polar-1632 is cartesian annular phase +shuffle, a scramble replicate (`not_detected` at 25.6 dB). True +Fourier-angle scramble of the same annulus is `not_detected` at 24.1 dB. +Radial-phase-only scramble is `not_detected` at 25.0 dB. One 90° +sector plus its conjugate stays `detected` at 27.5 dB. Affine/rotation +search of the 16-32 residual against the flat template does not lock +(lift 0.011, COCO 0.008). **Scale chirps.** Hyperbolic / Mellin monomials (arXiv:1208.5842): -real 1-D Mellin patterns tiled in 2-D, detected after a Radon-like -projection. Affine search of a 16-32 template is the cheap version. -Not yet run. +real 1-D Mellin patterns tiled in 2-D. Run 2026-08-23: +`r^{iα}` coefficients flat LOO 0.51, photo -0.27, COCO -0.58. +Log-polar `|F|` and a 64-bin radial Mellin profile saturate on COCO +(0.99). Not a payload, and not quieter than cartesian 16-32. **Directional packets.** Dual-tree complex wavelets (approximate analytic wave), Gabor/Morlet, ridgelets, curvelets, shearlets, @@ -294,7 +379,10 @@ packet energy is not the OpenAI payload. | Cascaded Fresnel / CGH | Two holograms at different depths | Hardware key. Not a pixel residual we can match-filter | A Fresnel/FrFT student without the distance or the fractional order -is another unmatched filter. +is another unmatched filter. Fresnel at z=8, 16, 32, 64 on the 16-32 +residual is a unitary copy of the cartesian band (flat LOO 0.75, photo +0.012). FrFT is the same unmatched-filter claim with an extra order +key; it does not isolate a photograph lock the four distances missed. **Cyclostationary and clock-warped waves.** Periodic clock change (Martin, Chabert, Lacaze, EUSIPCO 2005) turns a stationary host into @@ -307,18 +395,26 @@ new evidence. `(r,θ)` vs `log r`, the generating function (sinusoid, chirp, Bessel, Zernike), additive vs multiplicative, and the symmetry it claims. Then pick one attack that kills that symmetry and one that -should not. Cartesian 16-32 scramble, polar 16-32 scramble, 2 px -shift, and a small rotation are the four cheap probes. Shift already -left OpenAI `detected`. Polar scramble is prepared. Affine/rotation -search is not. +should not. Cartesian 16-32 scramble and a 2 px shift are done +(scramble kills, shift does not). True Fourier-angle scramble kills s1 +at 24.1 dB. Radial-phase scramble kills at 25.0 dB. A 90° sector does +not. Y scramble kills; Cb/Cr do not. Affine, Mellin, Zernike, PCET, +and Fresnel of the 16-32 residual do not lock on photographs. ## Still open or incomplete - Google: no public payload decoder and no usable programmatic oracle. The Gemini app remains quota-limited. Vertex was 403. -- `chatgpt-image-latest` encoder-off pairs: `models.retrieve` returns the - id, `images.generate` is 403 until the organization is verified - (re-checked 2026-08-23). `gpt-image-2` remains the working pair mint. +- `chatgpt-image-latest` is an optional third pair mint, not a blocker. + `gpt-image-1`, `gpt-image-1.5`, and `gpt-image-1-mini` are encoder-off. + `gpt-image-2` and dated `gpt-image-2-2026-04-21` are encoder-on, same + 16-32 stamp (corr 0.189 on gray). Latest would only matter if ChatGPT's + current consumer id used a different ensemble. `images.generate` is 403 + until the organization is verified. +- Physical print-scan: Brother DCP-L2520DW is idle and accepting. No + `scanimage`, no ImageCapture pyobjc. Recapture needs a human at the + flatbed. Simulation at 24.95 dB stayed `detected`. Do not print + unattended. - Adding unmarked context (frame, pad, hstack, collage) to hunt a residual is a presentation gate, not a mark statistic. Those rungs belong with identity and layout below, and with @@ -350,31 +446,56 @@ verifier window. Jacobian / adaptive queries against | CDMA Gold / m-sequence in the 16x16 fold | At chance for length 255 | | Rows as a pitched waveform | COCO noise has the same peak-to-mean | | The photo mark is the flat stamp at an unknown 16-phase | Exhaustive shift does not lift NCC | +| The photo mark is the flat stamp at a small rotation or 3% scale | Affine search lift 0.011, COCO noise 0.008 | | Self-keyed predictor from a 16 px luma thumb | Already 0.48 vs L1, 0.50 vs COCO (`self-keyed.json`) | | Global multiplicative cyclostationarity (H2) | Official positives below controls, 2026-08-14 | +| Mellin radial profile / log-polar \|F\| | Saturates on COCO (0.99). Annulus envelope | +| Scale chirps `r^{iα}` | Flat 0.51, photo -0.27, COCO -0.58 | +| Zernike n≤6 | Flat 0.77, photo -0.007, COCO 0.23 | +| PCET polar harmonics | Flat 0.75, photo 0.044, COCO 0.35 | +| Fresnel z=8..64 of 16-32 | Copy of cartesian LOO | +| 8-bin orientation energy | Saturates on COCO | +| Chroma 16-32 on gray flats | Cb 0.064, Cr 0.025 vs Y 0.682. Stamp is luma | ### Not a watermark, might still be an AI-vs-camera extra +Battery 2026-08-23, `remaining-hypotheses-2026-08-23.json`. Kodak corpus was empty here, camera arm is COCO plus the photo-pair sources. + | Hypothesis | Result | | --- | --- | -| Absence of camera PRNU | Gray `gpt-image-2` highpass RMS 0.25 vs COCO 14.6, that is missing texture, not a missing sensor. A Wiener PRNU residual on photographs is still open as a Model 1 sibling, not as SynthID | -| JPEG ELA | Flat 0.49, s1 1.97, COCO 3.13. Compression history, not a payload | +| Absence of camera PRNU | Gray highpass RMS 0.25 vs COCO 14.6 was texture. Wiener residual on *photographs*: `gpt-image-2` edits 4.61 vs camera 8.05. Direction is camera-like leftover of the donor JPEG, not a missing sensor, and not a payload | +| JPEG ELA | Flat 0.49, s1 1.97, COCO 3.13. Compression history | +| CFA interpolation error (Bayer as detector) | Ratio photo-edit 0.117 vs camera 0.184 vs gray stamp 0.588. Weak camera vote, overlaps. Inverse of the Bayer remover, not SynthID | +| JPEG ghosts (Farid) | s1, a `gpt-image-2` photo, and a camera JPEG all minimize at Q90 with similar spreads. Codec, not a payload | +| PNG Paeth / filter-byte residual | `gpt-image-2` PNG is 99.9% Paeth. Camera re-saved PNG 73% Paeth, s1 74%. Export encoder fingerprint | +| Perfect-circle / text-edge rate | Hough circles per MP 385 (edits) vs 536 (camera). Edge fraction 0.052 vs 0.072. Too noisy for a payload or a provider | +| Face-gated 16-32 | s1: 3 Haar faces, inside RMS 12.6 vs outside 10.9. One photo with faces: outside/in 1.49. No systematic "spend the mark off faces" | +| CLIP-space watermark | That is Model 1. Not a payload decoder | -### Still crazy, not yet measured +### Non-local, 2026-08-23 -- Content-locked affine search (small rotation plus 16-32 NCC), not origin-locked. Published analog: Fourier-Mellin / log-radial harmonics (Ó Ruanaidh and Pun 1998). Polar 16-32 scramble is the remover twin, already rastered at 25.6 dB. -- CFA presence as a camera vote (Bayer as a *detector* feature, the inverse of the remover arm). Published analog: Zhong, Xu, Zou [arXiv:2601.22778](https://arxiv.org/abs/2601.22778) (DCCT). Farid's 2005 CFA-interpolation test is the classical form. -- Wavelet Wiener PRNU on `gpt-image-2` photo edits versus Kodak. Published analog: Klier and Baier, DFRWS EU 2026, PCE vs smartphone fingerprints (ChatGPT-5 FPR 100% until a center crop). -- PNG Paeth / filter-byte residual after a lossless rewrite. -- Double-JPEG ghosting as an export fingerprint. Farid TIFS 2009. ELA already failed as a payload; the ghost sweep is the remaining codec check, JPEG-only. -- Face-gated 16-32: maybe the encoder spends budget off faces. -- Baker-map / area-preserving scramble of the mid band. -- Print-scan (physical). -- Nested open watermark plus SynthID. -- Mark in ICC / cICP / gamma, not in pixels. Strip-and-reencode already used for the oracle path; a pixel-preserving ICC rewrite is the remaining check. -- Encoder ensemble that does not recognize itself (patent). Untestable without that pair. -- Photon-shot / Poisson-domain embedding. -- CLIP-space watermark. Would show up as Model 1, not as a payload. +Battery `.local-eval/synthid/prc-oklab-attack-2026-08-15/nonlocal-2026-08-23/`. +Oracle after AI-metadata strip, 25 s gap, then one dated-id retry after a 429. + +| Hypothesis | Result | +| --- | --- | +| HEIF q80 / q50 | 46.3 / 39.3 dB, official `detected` | +| AV1 CRF 32 still | 37.2 dB, `detected` | +| Print-scan simulation (0.35 deg, blur σ 0.9, 300/360 dpi, JPEG q42) | 24.95 dB, still `detected`. Same PSNR class as 16-32 scramble, which kills | +| Physical print-scan | Brother DCP-L2520DW idle and accepting. No `scanimage`, no ImageCapture pyobjc. Not printed unattended | +| `gpt-image-1.5` gray reproduce | C2PA `created, converted`. Oracle `not_detected`. 16-32 corr vs `gpt-image-2` stamp 0.003. Encoder-off. Dirty redraw 24.0 dB | +| `gpt-image-1-mini` gray reproduce | Same C2PA. Oracle `not_detected`. Corr 0.003. PSNR 31.1 dB | +| `gpt-image-2-2026-04-21` gray reproduce | C2PA `created, converted, watermarked.unbound`. Official `detected`. 16-32 corr vs unversioned `gpt-image-2` stamp 0.189. Same encoder family. PSNR 47.5 dB | +| `chatgpt-image-latest` generate | 403, org verification. Listed among image models, not callable | +| DIRE SDXL VAE + DDIM float32 | VAE RMS 512: gray 1.24, s1 9.15, photo edit 9.89, camera 11.84. DIRE RMS: gray 2.40, photo 30.9, s1 31.5, camera 33.0. Texture rank, not a payload | + +### Still blocked after that battery + +| Hypothesis | Why it stays blocked | +| --- | --- | +| Physical print-scan recapture | Human at the flatbed | +| Encoder ensemble that does not recognize itself | Needs another actual SynthID encoder/decoder pair. Extra OpenAI ids did not mint one. Open-proxy transfer is already closed: source-matched TrustMark, VideoSeal, DWT-DCT, and WAM pairs produced held-out-family AUC 0.437-0.562, so another generic public pair does not answer this hypothesis | +| `chatgpt-image-latest` as a third pair mint | `images.generate` 403 until org verification. Optional: only if ChatGPT latest used a different ensemble than `gpt-image-2` | Do not train on official decoder bits beyond the frozen L1 study. Do not mint a 128-photo student on the flat stamp. The information budget and @@ -398,15 +519,17 @@ All three `detected` before attacks. ## Source-matched pairs (2026-08-21) `gpt-image-2` (ChatGPT Images 2.0) can mint encoder-on/off pairs. -`chatgpt-image-latest` still 403 on generate (org verification), -re-checked 2026-08-23; retrieve of the model id succeeds. +`chatgpt-image-latest` is optional and 403 until org verification. | Input | C2PA | Oracle | Aligned PSNR | | --- | --- | --- | ---: | | Camera JPEG 960x1280 | none | not_detected | - | | ChatGPT UI + frame 1086x1448 | watermarked.unbound | detected | 16.6 dB (redraw) | | `gpt-image-1` edit, high fidelity, red dot | created, converted only | not_detected | 30.9 dB | +| `gpt-image-1.5` gray reproduce 1024 | created, converted only | not_detected | 24.0 dB (redraw) | +| `gpt-image-1-mini` gray reproduce 1024 | created, converted only | not_detected | 31.1 dB | | `gpt-image-2` edit, red dot 1024x1536 | watermarked.unbound | detected | 28.2 dB | +| `gpt-image-2-2026-04-21` gray reproduce 1024 | watermarked.unbound | detected | 47.5 dB | The `gpt-image-2` photo residual is broadband (std 9.1), not a 16-32 stamp. COCO `gpt-image-2` edits: 11/12 `watermarked.unbound`, one safety block. diff --git a/docs/synthid-oracle-ladders.md b/docs/synthid-oracle-ladders.md index a124a41..7d3bd84 100644 --- a/docs/synthid-oracle-ladders.md +++ b/docs/synthid-oracle-ladders.md @@ -10,7 +10,7 @@ | Page | Use it for | | --- | --- | -| [SynthID local detector research](synthid-detector-research.md) | Hunt for a keyless local mark detector. Closed. | +| [SynthID local detector research](synthid-detector-research.md) | Hunt for a keyless local mark detector. Open. Closed routes on that page. | | [Classifier models](synthid-classifiers.md) | Model 1 AI-versus-camera result, rejected provider CLIP, `pipeline_lattice` as google-lineage. | | [SynthID mark removal research](synthid-removal-research.md) | Quiet-remover hunt. Closed except ~19-24 dB 16-32 scramble and blur sigma 7. | | [Mechanism reference](synthid.md) | How SynthID works, provenance, robustness, regeneration. | @@ -32,9 +32,20 @@ | Photo `d'` budget 13.4 dB, 128-photo student, 16-32 residual without flat `G` | [detector](synthid-detector-research.md) | | OKLab codeword replacement, add-context as presentation | [removal](synthid-removal-research.md) | | Three-class OpenAI / Gemini / photo ask | [classifiers](synthid-classifiers.md) | -| Wild hypotheses 2026-08-23 (sort, CDMA, bispectrum, PRNU, affine-not-run) | [detector](synthid-detector-research.md) | -| Prepared polar / band-transplant / palette64 | [removal](synthid-removal-research.md) | +| Wild hypotheses 2026-08-23 (sort, CDMA, bispectrum, PRNU, affine 16-32 NCC no lock) | [detector](synthid-detector-research.md) | +| Wild oracle 2026-08-23: misnamed polar-1632 is cartesian scramble replicate `not_detected`; band-transplant `not_detected`; palette64 `detected` | [removal](synthid-removal-research.md) | | External literature 2026-08-23 (Gowal, AWPD, PRC, Zhao, UnMarker, CtrlRegen, MarkNull, reverse-SynthID) | [detector](synthid-detector-research.md), [removal](synthid-removal-research.md), [classifiers](synthid-classifiers.md) | | Adjacent literature, not SynthID (Cox, HiDDeN, StegaStamp, Tree-Ring, Ojha CLIP, Corvi Fourier, DCCT CFA, PRNU PCE) | [detector](synthid-detector-research.md), [classifiers](synthid-classifiers.md), [removal](synthid-removal-research.md) | | Image investigation and data hiding (LSB, UNIWARD, Baluja, HiNet, Gaussian Shading, ELA, JPEG ghosts, DIRE, CNNDetect) | [detector](synthid-detector-research.md), [classifiers](synthid-classifiers.md) | | Waveforms in a picture (DFT, Fourier-Mellin, Zernike, chirps, Fresnel, DRPE, cyclostationary) | [detector](synthid-detector-research.md) | +| Remaining hypotheses 2026-08-23 (CFA, JPEG ghost, Paeth, face-gate, Baker, Poisson, nested LSB, angular scramble) | [detector](synthid-detector-research.md), [removal](synthid-removal-research.md), [classifiers](synthid-classifiers.md) | +| Non-local 2026-08-23 (HEIF/AV1 survive, print-scan sim 24.95 dB still detected, gpt-image-1.5/mini encoder-off, dated gpt-image-2 same stamp, DIRE DDIM texture) | [detector](synthid-detector-research.md), [removal](synthid-removal-research.md), [classifiers](synthid-classifiers.md) | +| Waveform shells 2026-08-23 (Mellin/Zernike/PCET/Fresnel no photo lock; Y scramble kills, chroma and 90° sector do not; radial-phase kills) | [detector](synthid-detector-research.md), [removal](synthid-removal-research.md) | +| Public decoder sweep 2026-08-23/24 (`Rinne414` fixed templates 0/464 on new OpenAI/Google/camera challenge; injected template spoofs the public correlator, but 0.25-2x subtraction stays official `detected` at 43.13-25.72 dB) | [detector](synthid-detector-research.md), [removal](synthid-removal-research.md) | +| Public CNN sweep 2026-08-24 (`newideas99` ensemble accepts 53/64 personal cameras and has OpenAI-vs-camera AUC 0.549; a whole-frame gradient makes the ensemble effectively zero but stays official `detected` through ±8/255 / 34.30 dB) | [detector](synthid-detector-research.md), [classifiers](synthid-classifiers.md), [removal](synthid-removal-research.md) | +| `reverse-SynthID` V4 repeat 2026-08-24 (77/200 Google, 76/200 OpenAI, 27/64 cameras at the published cut; AUC 0.510; Round-06 manual Gemini verdicts are not published as per-image evidence) | [detector](synthid-detector-research.md), [classifiers](synthid-classifiers.md), [removal](synthid-removal-research.md) | +| Broad GitHub sweep 2026-08-24 (133 unique primary repositories; REGRET and the vordme flat-field SVM fail the strict v7 transfer; literal ports and generic heuristics add no signal) | [detector](synthid-detector-research.md), [classifiers](synthid-classifiers.md) | +| Additional public removal sweep 2026-08-24 (DeSynth stays official `detected`; froggeric and other ControlNet/diffusion projects corroborate lossy regeneration; PortOS closes high-fidelity phase/noise jamming) | [removal](synthid-removal-research.md) | +| Google verifier surfaces 2026-08-24 (retired Vertex `imageverification@001`; live but unlisted and inaccessible `synthid.googleapis.com/upload/v1:verifyContent`) | [detector](synthid-detector-research.md) | +| Metadata-free source hunt 2026-08-24 (1% cascades rejected; frozen multiscale fusion found 276/600 OpenAI-or-Google targets, 0/1,000 photographs and 1/25 TC260 on blind v4) | [classifiers](synthid-classifiers.md) | +| Original-export source hybrids 2026-08-24 (frozen v7 215/400 exact; post-hoc v8 292/400 and per-codec v11 316/400 exact, 0/564 independent camera errors; local precision scan 131 OpenAI plus 17 Gemini candidates) | [classifiers](synthid-classifiers.md) | diff --git a/docs/synthid-removal-research.md b/docs/synthid-removal-research.md index 262296e..d2430cb 100644 --- a/docs/synthid-removal-research.md +++ b/docs/synthid-removal-research.md @@ -16,12 +16,20 @@ Bayer, VNG demosaic, upscale-then-Bayer, barrel distortion, scanline jitter, and a 2 px shift closed 2026-08-22 on s1/s2 and 2026-08-23 on s3 and fish: they leave the official oracle `detected`. -Working residual kills on photographs cost about 19-24 dB: +Working residual kills on photographs cost about 19-26 dB: -- 16-32 px phase scramble (s1 24.6 dB, fish 24.3 dB, s2 19.0 dB) +- 16-32 px cartesian phase scramble (s1 24.6-24.8 dB, fish 23.2 dB, s2 19.0 dB) +- Fourier-angle scramble of the same annulus (s1 24.1 dB) +- Radial-phase scramble of the same annulus (s1 25.0 dB) +- Y-only 16-32 scramble (s1 24.6 dB); Cb/Cr-only do not kill +- File named polar-1632, actually cartesian (s1 25.6 dB) +- Replace 16-32 with a COCO photo's 16-32 (s1 25.2 dB) - Gaussian blur sigma 7 (23.8 dB), holds 3/3 versus sigma 6 - Additive 16-32 jam only at a=24 / 18.6 dB, worse than scramble +Baker-map, 8-seam carve, Poisson, nested LSB, palette64, and ICC rewrite +do not kill at a better PSNR. + JPEG q5, noise sigma 16, grayscale, rot90, flip, 5°, downscale 0.20x, median 7, posterize 4, VAE round-trip, and white pad to 40% linear stay `detected`. Elastic warp is not a stable kill (s3 still `detected` at @@ -47,6 +55,13 @@ presentation gate, not residual damage. Those rungs are in | TrustMark-style micro-warp | 2026-08-21 | 0.25 px / 32 dB still 100% detect on TrustMark P; OpenAI elastic ~21 dB unreplicated | | OKLab random-codeword replacement as a quiet wipe | 2026-08-15 | On four public Google-oracle positives, replacing the period-16 tile at 0.95 dropped the *local* lattice score below 0.173 at ~54 dB. Gemini pixel verify never accepted the candidates (`Connecting to Verify AI`). Local-score intervention, not an official wipe | | PRC-style OKLab a/b noise plus spectral peak cleaning | 2026-08-15 | Independent high-pass OKLab noise at 32.6 dB moved the median local score by only `-0.0219`. Comb suppression moved one of four below threshold at 58 dB. Not a quiet official kill | +| Rinne414 fixed-template subtraction | 2026-08-24 | The pinned pre-May GPT-Image2 residual was resized onto a current verified OpenAI image and subtracted at 0.25x, 0.5x, 1x, and 2x. Official SynthID stayed `detected` at 43.13, 37.49, 31.60, and 25.72 dB after metadata stripping. Even the dirtiest rung is no better than the existing 24-25 dB annulus-phase scramble. The template can spoof its own public correlator but does not cancel the current mark | +| `newideas99` CNN gradient | 2026-08-24 | A 3x3 crop-grid objective spread the white-box perturbation over the full marked frame. The frozen ensemble fell from 0.99995 to 0.25956 at ±2/255 (45.92 dB) and to effectively zero at ±4/255 (40.30 dB). Official OpenAI SynthID stayed `detected` at ±1, ±2, ±4, and ±8/255, through 34.30 dB. The gradient attacks the surrogate's shortcut, not the production mark | +| `reverse-SynthID` V4 Round-06 | 2026-08-24 | The advertised `final`/`nuke` path is SD-VAE regeneration plus elastic and affine warps, resize squeeze, color change, residual FFT subtraction, and a JPEG/noise chain, with PSNR floors of only 14/11 dB. The repository claims 20 manual Gemini-app successes but contains no manifest, tally, or per-image verdicts. Its four bundled older cleaned pairs are 45.7-50.2 dB, yet the reproduced V4 score rises on three and is nearly unchanged on the fourth. No callable Google pixel oracle was available for an independent Round-06 verdict. This is an unverified lossy regeneration/distortion stack, not a quiet pattern cancellation | +| [`0xROOTPLS/DeSynth`](https://github.com/0xROOTPLS/DeSynth/tree/96db920731c2a3d04bf13163a5077b9a67706d1b) | 2026-08-24 | Qwen Image img2img at strength 0.25, followed by a Gaussian frequency split that restores the source high frequencies above sigma 1.95. The repository's public OpenAI original, default output, and edge-guided output all returned official `detected` in a current repeat after metadata stripping. The published `not found` claim does not reproduce against the current OpenAI oracle | +| [`froggeric/gemini-watermark-and-synthid-remover`](https://github.com/froggeric/gemini-watermark-and-synthid-remover/tree/5918384ce403968de0560cefd889e50eba0163bc) | 2026-08-24 | SDXL img2img with a documented manual Google-verifier ladder. The author reports 7/8 clears at strength 0.08 and 9/9, including a double mark, at strength 0.10 with five effective denoise steps and PSNR 29-41 dB. The exact nine before/after verdict artifacts are not tracked, so this is useful external regeneration corroboration, not an independently reproduced oracle result | +| [`atomantic/PortOS`](https://github.com/atomantic/PortOS/tree/b11a93e110262925c64a1b145a154ca87b340055) adversarial-jamming experiment | 2026-08-24 | Its own one-image manual OpenAI run found that quality-preserving phase noise, band noise, blur, and 0.70 resize squeeze stayed detected. Only visibly destructive phase perturbation cleared. A 0.85-0.90 resize caused repeated detector timeouts, which the repository correctly keeps separate from `not_detected`. This independently closes high-fidelity additive/phase jamming, but the source artifacts are not published | +| Generic regeneration claims | 2026-08-24 | `mertizci/noai-watermark`, `BovineOverlord/Loyal-Bear`, `obaskly/NeuralBleach`, and `tymongumienik/unwatermark` are SD/CtrlRegen/ControlNet redraws. Their algorithms are already covered by the product's regeneration remainder and the CtrlRegen literature. README verdicts without a frozen manifest do not establish a quieter or more reliable operating point | | Add unmarked context (frame, pad, hstack, collage) | 2026-08-19 | Official `not_detected` is a presentation gate. White pad 40% linear stays `detected`; photo fill at the same geometry is `not_detected`. See detector identity/layout | | `cebeuq/Synthid-Bypass` diffusion reconstruction | 2026-08-13 | 12 public pairs. Lattice and Gemini Verify go quiet on the *after* images because the image was redrawn, not because a payload was deleted. Faces and text are a quality claim for regeneration, not a local wipe | @@ -140,23 +155,62 @@ Surround: photo fill at the white-pad geometries is `not_detected` on between 25% width (`detected`) and 35% (`not_detected`). Photo frame 15% each side is `not_detected` on 3/3; 12% does not hold. -## Wild removers, oracle not yet run (2026-08-23) +## Wild removers (oracle 2026-08-23) -Prepared on s1. PSNR only. Bayer fish is complete. Submit these when the -rate limit allows, not as a new training loop against the verifier. +Preregistered on s1, one pass, 25 s gap. Manifest: +`.local-eval/synthid/prc-oklab-attack-2026-08-15/wild-attacks-2026-08-23/oracle-manifest.json`. -| Attack | PSNR | Note | +| Attack | PSNR | Verdict | Note | +| --- | ---: | --- | --- | +| Replace 16-32 with a COCO photo's 16-32 | 25.2 | not_detected | Same annulus as cartesian scramble (24.6 dB). Substituting a camera band kills the decoder, 0.6 dB quieter than scramble on s1, not a new quality class | +| File named polar-1632 | 25.6 | not_detected | Misnamed. The raster randomizes cartesian FFT phase in the 16-32 annulus, same family as scramble (24.6 dB). It is a scramble replicate, not a `(r, θ)` polar test | +| 64-color median-cut palette | 35.6 | detected | Quieter than scramble and still marked. Posterize-4 already stayed `detected`; a smarter quantizer is not enough | +| PIL RGB to CMYK to RGB | inf | not submitted | No-op on this PNG | + +The 16-32 kill is luma phase in that annulus. Cartesian, Fourier-angle, +and radial-phase all silence the decoder near 25 dB. A 90° sector of the +same ring does not (27.5 dB `detected`). Cb-only and Cr-only 16-32 +scrambles stay `detected` at 44-45 dB. A foreign-scene transplant of the +same band also silences the decoder near 25 dB. Palette, Baker-map, seam +carve, Poisson, nested LSB, and ICC do not. + +Follow-up 2026-08-23, s1, 25 s gap, `remaining-2026-08-23/oracle-manifest.json`: + +| Attack | PSNR | Verdict | | --- | ---: | --- | -| Replace 16-32 with a COCO photo's 16-32 | 25.2 | Band transplant. If this ever reads `not_detected` near 25 dB it is the quietest residual kill so far; if `detected`, the mark is not a replaceable additive layer in that annulus | -| Polar phase scramble of 16-32 | 25.6 | Same band as the cartesian scramble (24.6 dB `not_detected`). Tests circular / Fourier-Mellin / polar-harmonic families: energy stays, angle dies | -| 64-color median-cut palette | 35.6 | Quieter than scramble. Posterize-4 already stayed `detected`; this is a smarter quantizer | -| PIL RGB to CMYK to RGB | inf | No-op on this PNG. Not an attack | +| Fourier-angle 16-32 scramble | 24.1 | not_detected | +| Cartesian 16-32 scramble (replicate) | 24.8 | not_detected | +| Baker-map of the 16-32 band | 27.8 | detected | +| Poisson noise | 30.7 | detected | +| Nested LSB in blue | 55.9 | detected | +| Seam carve 8 | 27.7 | detected | +| ICC sRGB rewrite | inf | not submitted, no-op | -Files: `.local-eval/synthid/prc-oklab-attack-2026-08-15/wild-attacks-2026-08-23/`. +Non-local codecs, 2026-08-23, s1, 25 s gap: -Also untested: seam carving of the mid band, CMYK via a real ICC printer -profile, HEIF/AV1 round-trip, background-only 16-32 scramble (face mask), -print-scan. +| Attack | PSNR | Verdict | +| --- | ---: | --- | +| HEIF q80 | 46.3 | detected | +| HEIF q50 | 39.3 | detected | +| AV1 CRF 32 | 37.2 | detected | +| Print-scan simulation | 24.95 | detected | + +Physical print-scan is still blocked unattended (Brother DCP-L2520DW idle and +accepting, no `scanimage`, no ImageCapture pyobjc). Face-gated scramble is +unnecessary: Haar on s1 put *more* 16-32 energy on faces. Generic 25 dB is +not the kill: this simulation stays `detected` at the PSNR where 16-32 +phase scramble does not. + +Waveform-shell splits, 2026-08-23, s1, 25 s gap, +`waveforms-shells-2026-08-23/oracle-manifest.json`: + +| Attack | PSNR | Verdict | +| --- | ---: | --- | +| Y-only 16-32 scramble | 24.6 | not_detected | +| Cb-only 16-32 scramble | 45.0 | detected | +| Cr-only 16-32 scramble | 43.9 | detected | +| 90° Fourier sector of 16-32 | 27.5 | detected | +| Radial-phase-only 16-32 | 25.0 | not_detected | ## External literature (surveyed 2026-08-23)