Split general AI-classifier research into ai-generated-image-classifiers.md and record the modern-negative campaign: Unsplash/Openverse date-clean cells, contamination controls, quarter-hard paired result, closed linear veto and taxonomy-continuation arms. pre-commit: 1) maintain.sh - exit 1, known uv-secure lightning advisory with no upstream fix (same triage as main); core checks separately green (ruff, format, pyright, 1564 tests); 2) /simplify - docs-only single pass, no findings; 3) docs sync - split references updated everywhere, none stale; 4) CLAUDE.md - routing line already updated, compliant
48 KiB
SynthID local detector research
Research archive for the hunt for a local, keyless SynthID pixel detector. Not a statement of current product capability. Shipped behavior: supported signals and known limitations.
Sister pages: SynthID source classifiers, SynthID mark removal, mechanism reference. Dated measurements live in the chronological plan.
Result
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
secret in intermediate layers, encoder/decoder ensembles that do not
recognize each other). Without that pair, the residual sits under the
scene. Keyless energy, TrustMark transfer, L1 distillation, a flat-field
stamp, and a 16-32 band student all failed to read the official oracle
contrast on photographs.
S4, 2026-08-15: the two providers are not doing the same thing. Cross-image
correlation of the folded residual is high for Google (tile16 pos-pos
+0.326, chance 0.036) and at chance for OpenAI (+0.032). Google
shares one fixed phase-coherent pattern, also present in its controls at
about half the amplitude. OpenAI shares nothing, which is what a
content-dependent post-hoc encoder produces. Comb experts that work on
Google therefore cannot be reused as an OpenAI watermark detector.
M2, 2026-08-15, re-verified 2026-08-16: Google unwatermarked pairs cannot
be minted. imagen-* ids 404 from the model garden. gemini-*-image
rejects addWatermark (Cannot find field). Current Gemini API docs
state that all generated images include a SynthID watermark. There is no
encoder-off Google path.
What the product uses for the watermark is signed provenance and
verify-openai-synthid. The periodic-lattice expert is research-only under
scripts/synthid_runtime/ and is not called from identify or the CLI.
Lineage measurements of that expert are in
SynthID source classifiers.
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 |
A reproducible fixed-residual correlator and a useful spoofability negative control | Current-image detector or fixed-template remover | All three templates detected 0/400 current OpenAI and Google images. 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 |
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 retained 172/200 OpenAI but accepted 110/200 Google. A gradient drove the surrogate effectively to zero, but official SynthID stayed detected through +/-8/255 at 34.30 dB |
aloshdenny/reverse-SynthID |
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 and 76/200 OpenAI at the same cut. Round-06 has no published per-image oracle evidence and uses regeneration/distortion with 14/11 dB PSNR floors |
Ristellise/REGRET |
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 214/600 disjoint ImageNet photographs |
vordme2010/synthid-dataset |
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 and 0/200 OpenAI on v7 |
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 SynthID source classifiers and mark removal.
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/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 and 1/200 OpenAI. 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 and 76/200 OpenAI. 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 |
| U1: one feature space for both providers | 2026-08-15 | Transfer 0.535 and 0.469 |
| Hand statistics vs a perceptually masked keyed mark (M1b) | 2026-08-15 | At equal RMS, fixed 0.670, keyed 0.669, keyed+masked 0.546. Masking, not keying, defeats hand features |
| Decoder-substitution / foreign VAE as a verified negative | 2026-08-17 | OpenAI oracle stayed detected at 22.3 dB. Attacking a positive does not mint a labelled negative |
aoxo/reverse-synthid as extra Google templates |
2026-08-19 | Hugging Face dump scored against the frozen era bank. Extra family means raised foreign scores instead of isolating a mark |
| Origin-locked lattice as SynthID | 2026-08-16 | Two-pixel crop kills it; published SynthID keeps 99.97% TPR under aggressive crop. See classifiers for google_lineage_renderer |
| Keyless energy in 16-32 px | 2026-08-20 | L1 AUC 0.53; official decoder reads phase structure, not energy |
| TrustMark / open-encoder transfer | 2026-08-20 | E3 leave-one-encoder-out at chance on TrustMark (0.505 ridge, 0.510 conv) |
| L1 distillation of oracle bits | 2026-08-20 | Geometry-only AUC 0.78-0.83 beats pixel 124-d (0.64). ChatGPT export and opened C2PA predict not_detected. Inside 1254x1254, permutation p=0.45 |
| Flat 16-32 matched filter | 2026-08-21 | Leave-one-out residual correlation 0.645 on gray flats; 0.007-0.025 on COCO photo residuals. L1 AUC 0.70 was a size confound (size-matched 0.59 / 0.44) |
gpt-image-1 as encoder-off pair |
2026-08-21 | Does not stamp. gpt-image-2 does |
| CNN on raw L1 bits | 2026-08-21 | Do not train. Labels are export geometry and presentation, not the mark |
| 128-photo causal wavelet student on the flat template | 2026-08-21 | Photo 16-32 jam flips only at a=24 / 18.6 dB (a*_photo < 0.53 failed). A student cannot beat a matched filter if the photo-domain mark is that quiet |
| Photo 16-32 amplitude without the flat-arm template | 2026-08-23 | 11 COCO gpt-image-2 edits plus the red-dot pair. Residual is the camera JPEG resized onto the edit raster, top-left 32 px dropped. Median 16-32 residual RMS 12.2, same order as 8-16 (9.0) and 32-64 (16.3). On the five tightest pairs (full residual RMS < 16): 16-32 median 2.69, still ~24x the 0.11 flat stamp and not louder than 8-16 (3.81). The photo residual does not isolate a 16-32 codeword |
| Sort-by-luma 1D chroma stego | 2026-08-23 | Flat LOO 0.914 but a luma-order shuffle is already 0.792. COCO plus tiny noise: 0.642 vs shuffle 0.640. The sort invents the correlation |
| Retinex / local-gain then 16-32 LOO | 2026-08-23 | 0.742 vs plain 16-32 LOO 0.752 on the same eight gray flats. No new carrier |
| Distant 16-32 patch coupling | 2026-08-23 | Near lag 0.13 of a tile: -0.013. Far lag ~500 px: +0.054. No nonlocal lock |
| Bispectrum of the 16-32 ring | 2026-08-23 | Degenerate: 1.0 on flats and 1.0 on COCO. Not a statistic |
| 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 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 200 current OpenAI and 200 current Google images produced zero detections for all three published templates at the 0.08 cut; maximum GPT-Image2 score on OpenAI was 0.0167. Adding the expected template can spoof the public correlator, but that 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 CNN ensemble |
2026-08-24 | Exact frozen inference retained 172/200 OpenAI but accepted 110/200 Google at the published 0.5 cut. 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 SPAM model |
2026-08-24 | At the published cut, exact model inference accepted 139/200 Google, 141/200 OpenAI, 214/600 disjoint ImageNet photographs, and substantial fractions of foreign generators. The apparent high-precision tail did not transfer |
vordme2010/synthid-dataset 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 current OpenAI rows. 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)
On 11 gpt-image-2 photo edits, the flat-derived 16-32 template at full
amplitude against per-image whitening has median d' = 0.93 (range
0.68-2.46). That is a best-case single-image AUC of about 0.75 even with a
perfect, perfectly aligned template. A P5 gate (FPR 0.1%, TPR 90%) needs
d' >= 4.37. The deficit is 4.7x in amplitude, 13.4 dB, unless the
photo-domain mark is louder than the flat measurement. Titration said it
is not: fish 16-32 additive jam stays detected through a=16 / 21.9 dB.
2026-08-23, without using that flat stamp as G: the aligned photo
residual in 16-32 is redraw, not a codeword. Median RMS 12.2 across 12
pairs; 2.69 on the five tightest. Neighboring octaves are as loud.
.local-eval/synthid/prc-oklab-attack-2026-08-15/photo-band-amplitude-2026-08-23.json.
Do not report an AUC from those 11 pairs as a detector result. With n=11
the standard error on AUC is about 0.12. Notes:
.local-eval/synthid/prc-oklab-attack-2026-08-15/agent-detector-claude.md.
External literature (surveyed 2026-08-23)
Primary sources, not abstracts. Each row is mapped onto a closed or open route in this campaign. Mechanism detail stays in synthid.md. Removal papers are on mark removal. Classifier papers are on SynthID source classifiers.
Official mark, not a public decoder
| Source | What it is | Map to this campaign |
|---|---|---|
| Gowal et al., arXiv:2510.09263 | Post-hoc encoder f / decoder g. Detection logit is not payload recovery. SynthID-O (partner variant) 136 bits at 512x512. TPR at 0.1% FPR 99.98% aggregated, 99.97% on the hardest spatial crop+resize. Trains against sampled semantics-preserving transforms, including weak VAE regeneration. Production decoder unpublished |
Matches the architecture we treat as keyed x' = x + g(x). Explains why a two-pixel crop kills pipeline_lattice but not the official oracle, and why a 22.3 dB foreign VAE still reads detected |
| DeepMind US12094474B1 and continuation US20250149048A1 | Residual U-Net encoder, separate decoder, optional key, encoder/decoder ensembles that need not recognize each other | Constraint, not a recipe. Ensemble non-recognition is why one recovered Google tile cannot be reused as an OpenAI detector (S4) |
| Dathathri et al., Nature 634:818-823 (2024) | SynthID-Text: tournament sampling of LLM tokens, open-source | Different system. Image/audio/video remain proprietary |
| OpenAI, advancing content provenance (2026-05-19, audio 2026-07-31) and content provenance API | ChatGPT / API / Codex images carry C2PA plus SynthID. Audio from 2026-07-31. POST /v1/content_provenance_checks. not_detected does not rule out another vendor |
This is the oracle. C2PA and SynthID are independent entries. Do not abuse the endpoint as an adaptive reverse-engineering loop |
Keyless presence detectors in the literature
| Source | Claim | Caveat against our gates |
|---|---|---|
| Ao et al., arXiv:2603.06723 (AWPD / FSNet, SAFE@CVPR 2026) | Leave-one-algorithm-out presence detection. SynthID held out: FSNet Acc 0.894 / F1 0.886, ResNet-50 Acc 0.845 / F1 0.812, ConvNeXt V2 Acc 0.866. LSB and Patchwork both fail below 60%. Hypothesis: modern invisible marks share dense high-frequency spectral anomalies | UniFreq Table 3: SynthID is 2,000 images, all AIGC, zero photographs, from imagen-4.0-fast-generate-001 only, resized to 256x256. No OpenAI. No 0.1% FPR. Closest published analog to E3/L1 distillation. Our TrustMark leave-one-encoder-out was chance (0.505 ridge). Their high-frequency commonality is the same energy that L1 failed to read as an OpenAI payload |
aloshdenny/reverse-SynthID V3/V4; Google to The Verge, 2026-04-14 |
Spectral codebook from averaged Gemini flats. Spokesperson Myriam Khan: "It is incorrect to say this tool can systematically remove SynthID watermarks." The author also said the bypass confuses the decoder rather than deleting a payload | Our pickle-free V4 audit: paired AUC 0.517, frozen Open Images 386/1000 accepted. Not 0.1% FPR |
| Krawetz, Hacker Factor "Reversing SynthID" and "Meta's Un-Stable Signature" | Gemini chat TPR closer to 1/20 than the paper's 99.97%. Detector weak on flats. reverse-SynthID field accuracy ~70% vs the author's 90% | Gemini-app chat is not the OpenAI provenance API. Our gray gpt-image-2 flats are detected on the official OpenAI oracle. Do not mix the two verifiers |
| vitotitto LAB-a logistic (community, tiny holdout) | Reported 97.7% AUC on 20/20 | Not a P5 gate. Ignore as a detector claim |
Different embedding loci (not post-hoc SynthID)
These papers are often cited as if they were SynthID. They are not.
| Source | Locus | Why it is not this mark |
|---|---|---|
| Gunn, Zhao, Song, arXiv:2410.07369 (PRC, ICLR 2025) | Pseudorandom error-correcting code in the initial diffusion latent | Cryptographic undetectability is a latent-code property. SynthID-Image is applied after the VAE has already decoded pixels. Our OKLab "PRC-style" noise was a category error |
| Francati et al., arXiv:2509.10577 (EuroS&P 2026) | Crop-and-resize flipped about half of PRC latent signs and blocked belief-propagation decode | Confirms PRC is origin-locked in latent space. Matches why a 2 px shift kills pipeline_lattice and does not kill OpenAI SynthID |
| Fernandez et al. Stable Signature; Wen et al. Tree-Ring | Fine-tuned VAE decoder, or ring constraints on initial noise | In-generation. Google's paper is explicit that SynthID-Image does not modify the generator |
| TrustMark (arXiv:2311.18297), HiDDeN, StegaStamp | Open post-hoc encoder/decoder pairs | Transfer from these is E3: chance on TrustMark. WAVES (arXiv:2401.08573) stress-tests this family, not production SynthID |
Do not train a student on AWPD's Imagen-only 256 crop and call it an OpenAI SynthID detector. That would repeat L1's contamination: a generator/size cue, not a payload.
Adjacent literature, not SynthID
These papers are the published versions of the wild hypotheses and of Model 1. They detect something else: a camera pipeline, a generator fingerprint, an open watermark, or steganography. None of them is a keyless OpenAI payload decoder.
Classical spread-spectrum and open neural marks
| Source | What it is | Map |
|---|---|---|
| Cox, Kilian, Leighton, Shamoon, IEEE TIP 1997 | i.i.d. Gaussian vector in perceptually significant spectral components. Informed detector. Collusion-resistant by construction | Ancestor of keyed CDMA. Our length-255 m-sequence vs 16x16 fold was at chance because we did not have the key, and because OpenAI is content-adaptive, not a fixed Gold code |
| Zhu et al., HiDDeN, ECCV 2018 | Joint encoder / noise layer / decoder | Open pair. AWPD leave-one-out Acc 0.985. Transfer to SynthID is E3 |
| Tancik, Mildenhall, Ng, StegaStamp, 2020 | 100 bits at 400x400, trained through print-scan | Open pair. Survives recapture. WAVES: TPR at 1% FPR collapses from 1.00 to 0.01 under regeneration |
| Wen et al., arXiv:2305.20030 (Tree-Ring, NeurIPS 2023) | Pattern in the initial diffusion noise, recovered by DDIM inversion | In-generation, origin-locked in latent Fourier space. Crop-invariant by design. Not post-hoc SynthID |
| Fernandez et al., Stable Signature, ICCV 2023 | Fine-tune the LDM VAE decoder so every decode carries a bit string | In-generation. Gowal is explicit that SynthID-Image does not modify the generator |
| Lin and Juarez, arXiv:2506.10502 (USENIX 2025) | Public-knowledge attack that removes Tree-Ring | Confirms Tree-Ring is a different object with a different kill |
Steganalysis as a presence detector
Fridrich and Kodovsky Spatial Rich Models (TIFS 2012) and Boroumand, Chen, Fridrich SRNet (TIFS 2018) detect sub-bit-per-pixel spatial stego by high-pass residuals, with pooling disabled in the front of SRNet so the weak signal is not averaged away. AWPD cites both and says they drift on modern deep / generative marks. That matches our wavelet/FFT single-image detector (AUC 0.653, 0 TPR at a clean cut) and the 16-32 energy miss on photographs: a residual energy detector without the matching key is steganalysis of a mark that was trained not to look like LSB.
Generator fingerprints in the Fourier domain
Corvi, Cozzolino, Poggi, Nagano, Verdoliva, arXiv:2304.06408 (CVPRW 2023): GAN, diffusion, and VQ-GAN images show spectral peaks and anomalous autocorrelation; real vs synthetic differ in mid-high radial and angular power. reverse-SynthID averaged Gemini flats and called the peak a watermark codebook. Corvi's result says many generators leave some peak. Our V4 Open Images 386/1000 is what a generator-fingerprint detector looks like when you calibrate it as if it were a payload.
Yao and Juarez, arXiv:2512.11771 ("Smudged Fingerprints"): 14 fingerprinting methods across RGB, frequency, and learned features; removal attacks >80% white-box, >50% black-box. A fingerprint you can see without a key is a fingerprint you can wipe without a key.
Image investigation and data hiding (any method)
These are not SynthID papers. They are the rest of the toolkit: how people hide bits in pictures, and how people tell a picture was touched. Several of our wild hypotheses already had a published form here.
Hiding is not one problem. Cover modification (change an existing image), coverless / generative (sample an image that already carries the bits), and signed metadata (C2PA) fail under different attacks.
Cover modification, classical
| Source | Hide how | Detect / limit |
|---|---|---|
| LSB, Patchwork (Bender et al., IBM SJ 1996) | Flip low bits, or luminance of random pixel pairs | AWPD Acc < 0.60. Sparse or ±1 amplitude. SRNet / FSNet average it away |
| Westfeld F5 (2001), Fridrich nsF5 | JPEG DCT coefficients, matrix embedding | Histogram attacks on F5; nsF5 was the shrinkage fix. Domain is the codec, not a mid-band residual |
| Pevny, Filler, Bas HUGO (2010); Holub and Fridrich WOW (2012); Holub, Fridrich, Denemark UNIWARD (IH&MMSec 2013 / EURASIP 2014) | Content-adaptive costs, bits placed in texture via syndrome-trellis codes (Filler, IH 2011) | The modern spatial/JPEG floor. Distortion is designed to look like the cover. A 16-32 energy detector is the wrong statistic |
| Cox et al. 1997 | Spread-spectrum in significant DCT | Keyed. Already mapped above |
Cover modification, neural (hide a whole image, not 32 bits)
| Source | What it does | Map |
|---|---|---|
| Baluja, NeurIPS 2017, "Hiding Images in Plain Sight" | Full-resolution secret image distributed across all bits of a same-size cover | Capacity is the point. Not robust, not keyed provenance. HiDDeN later added a noise layer so the secret survives JPEG |
| Jing et al., HiNet, ICCV 2021 | Invertible neural net: hide and recover as one bijection | High-capacity lossless-ish hiding. Recovery needs the exact inverse, not an official oracle |
| Yang et al., PRIS, arXiv:2309.13620 | Invertible net plus robustness modules | Same family, trained through distortion |
A HiNet-style student on OpenAI pairs would learn the edit, not a SynthID codeword. That is the L1 contamination again.
Coverless / generative hiding
The cover is never modified because there is no cover. The sampler emits an image whose latents already encode the message.
| Source | Locus | Map |
|---|---|---|
| Yang et al., Gaussian Shading, arXiv:2404.04956 (CVPR 2024) | Map bits onto Gaussian latents indistinguishable from ordinary noise. Recover by DDIM inversion | Sibling of Tree-Ring / PRC. Training-free, performance-lossless for the generator. Not a post-hoc pixel stamp |
| Peng et al., StegaDDPM (ACM MM 2023) and later LDStega | Bits in the diffusion sampling distribution | Spatial SRNet is the wrong detector (NS-DSer, arXiv:2602.10219: move steganalysis into noise space) |
| CRoSS, Pulsar, MDDM | Message-to-noise projections | Same locus. A pixel scramble does not invert the sampler |
Passive forensics (the picture was touched, no secret assumed)
| 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 | 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 (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 (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
metadata --remove. Durable Content Credentials (spec 2.4) add a
soft binding that can re-link a stripped file to a repository. That
is provenance, not hiding.
Do not train on ELA, JPEG ghosts, DIRE, or a HiNet reconstruction and name the score SynthID.
Waveforms that can live in a picture
A mark is a function on the pixel lattice. The literature does not use one wave. It picks a basis whose symmetries match the attack it fears, then hides a keyed coefficient vector in that basis. Cartesian 16-32 is one shell. Polar, scale, and diffraction are different shells.
Standing waves on a rectangle. DFT / DCT / DST. A 2-D sinusoid
cos(2π(ux + vy)/N). JPEG lives here. Our octave scramble destroys
one annular radius of these frequencies, not one orientation. A
Gabor packet is the same sinusoid windowed in space.
Circular and log-radial waves. Functions of (r, θ), not
(x, y).
| Basis | Wave | Invariance it buys |
|---|---|---|
| Fourier-Mellin / log-polar (Ó Ruanaidh and Pun, Signal Processing 1998) | r^{iα} exp(ikθ) after a DFT magnitude |
Rotation and scale become translations |
| Logarithmic radial harmonics (IH 2002) | Same family, added in pixels, detected by complex correlation | RST without going through the unstable log-polar resample |
| Polar harmonic transforms: PCET, PCT, PST | exp(±i2π n r²) and polar cos/sin |
Rotation. Moments, not a dense codebook |
| Zernike / pseudo-Zernike | Orthogonal polynomials on the disk, radial part related to Bessel | Rotation. Classical moment watermark |
| 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 |
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. 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, contourlets, bandelets. Multiplicative spread-spectrum on curvelet coefficients is a published detector-design paper, not a SynthID decoder. Our wavelet summary AUC 0.653 already said a generic packet energy is not the OpenAI payload.
Optical diffraction, actual wave physics.
| Transform | What the wave is | Map |
|---|---|---|
| Fresnel | Quadratic phase exp(iπ r² / λz), a radial chirp. Energy concentrates with distance |
Holographic watermarks embed the diffracted field, not the picture |
| Fractional Fourier | Rotation of the time-frequency plane. Order is an extra key | Extra key space on top of DFT |
| Double random phase encoding (Réfrégier and Javidi, Optics Letters 1995) | Random phase at input and Fourier plane. Ciphertext is stationary white noise | Closest optical analog of a keyed x' = x + g(x) that looks like noise without both screens |
| 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. 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 a cyclostationary one by a periodic time warp. Our H2 multiplicative cyclostationarity test already put official positives below controls. Do not rerun the same statistic in a new basis and call it new evidence.
How to read a candidate wave. Name the coordinates (x,y) vs
(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 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-latestis an optional third pair mint, not a blocker.gpt-image-1,gpt-image-1.5, andgpt-image-1-miniare encoder-off.gpt-image-2and datedgpt-image-2-2026-04-21are 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.generateis 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 stayeddetected. 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 mark removal.
- Camera-to-ChatGPT "unchanged crop" pairs are dirty counterfactuals.
The instructed edit redraws; aligned PSNR on the frame pair was
16.6 dB. Compare pixels only after registration and a frozen residual
bound, as in the
gpt-image-2red-dot row.
A Gemini app caption that an image "looks like a photograph" is not a SynthID verdict. Use the provider pixel check or signed provenance.
Wild hypotheses
Battery 2026-08-23, no official oracle. Local numbers:
.local-eval/synthid/prc-oklab-attack-2026-08-15/wild-hypotheses-2026-08-23.json.
Prepared attack rasters wait in wild-attacks-2026-08-23/ for a later
verifier window. Jacobian / adaptive queries against
verify-openai-synthid stay out: the endpoint forbids reverse-engineering.
Tested locally, not a mark
| Hypothesis | Result |
|---|---|
| Chroma ordered by luma is a 1D payload | Correlation is an artifact of the sort |
Mark is g(x) of a Retinex envelope |
LOO unchanged vs the raw 16-32 residual |
| Nonlocal patch agreement in 16-32 | Far patches are not coupled |
| Quadratic phase coupling (bispectrum) | Statistic saturates on camera images too |
| 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 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 |
Non-local, 2026-08-23
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 the 2026-08-23 residual measurement both say the photo-domain mark is under the scene.
Oracle and seeds
Official POST /v1/content_provenance_checks, metadata stripped, pixels
preserved. Raw files stay gitignored under
.local-eval/synthid/prc-oklab-attack-2026-08-15/.
| Seed | Path | Size |
|---|---|---|
| s1 | originals/2026-05-31/31e55ea8a4de42029659654a80814630_src.png |
1024x1536 |
| s2 | originals/2026-05-31/37ae95821a3447c78f94e56bdebf0c88_src.png |
1024x1536 |
| s3 | originals/2026-07-10/d76f35fee69e4531865e88b786fa52e5_src.png |
1086x1448 |
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 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.
Solid gray/white through gpt-image-2 "reproduce exactly" is
watermarked.unbound. Gray 128 at 1024x1536: PSNR 41.9 dB vs the flat,
source not_detected, output detected. Other gray levels 32-220: PSNR
38-49 dB. Eight gray 1024x1536 residuals, leave-one-out correlation after
highpass: 0.645 (shuffle 0). That shared stamp does not transfer to COCO
photo residuals (0.007-0.025).
Presentation gate versus residual
An official not_detected is not one event. Collage, photo-pad, two-panel
self-concat, and 8x8 scramble can be a presentation gate (this upload is
not a single photograph). Blur sigma 7 and in-band 16-32 destruction sit on
the single-photo manifold and are residual damage; those belong in
mark removal.
Do not train a surrogate on mixed collage misses if the goal is a mark student.
Identity (s1, 2026-08-19): JPEG q80/q20, crop 2 px, crop 8 px, keep 0.75
and 0.50, rot90, rotate 5, flip, grayscale all stay detected.
Token / layout (s1): each quadrant at 512x768 detected; hstack and
vstack of marked|marked not_detected; 4x4 tile scramble detected;
8x8 not_detected. Two copies of a detecting image still miss. Tomography
3x3: all nine cells not_detected (a 1/9 window is below support).
Preprocess E1 (s1): stretch 2x detected; centre-crop of marked|marked
hstack back to native detected; 0.20x pixels on a native-size white
canvas not_detected (the same 0.20x file uploaded alone was detected).
L1 is not a mark task
A missing watermarked.unbound assertion is not a clean negative. On
2026-08-16 the official verifier called 65 of 94 OpenAI rows without that
assertion detected (69%), with 9 of 9 interleaved health positives
detected so the endpoint was answering. Google's own API emits watermarked
images with no assertion, per its documentation. Corpus AUCs that treat
"no assertion" as unmarked rest on a negative class that is roughly
two-thirds positive.
Control-only 283 rows: 203 detected, 80 not_detected. Forward-temporal
nested ridge on 124 pixel features: AUC 0.649 / 0.641. Geometry-only:
0.781 / 0.826. All 21 claim_generator=ChatGPT controls are
not_detected. C2PA opened: 24/24 not_detected. Inside 1254x1254,
mean-feature permutation p=0.45.
OpenAI-supervised ridge on 16-32 band-passed image_features:
forward-temporal AUC 0.53 vs L1 not_detected, 0.95 vs COCO, 0.97 vs COCO
after a 2 px crop. The student learns OpenAI-versus-photo and still does
not see the oracle mark contrast.
Product remainder for the watermark
Signed provenance (identify) and verify-openai-synthid (remote, explicit
upload). A research lattice miss is not a clean SynthID negative.