Skip to content

Repository files navigation

Veridict — Local AI Image Detector

A Google Chrome (Manifest V3) extension that detects AI-generated images entirely on your device — WebGPU/WASM inference via onnxruntime-web, no cloud services, no local servers, no telemetry. Every analyzed image gets a visible badge (AI 87% / Real 92%) and machine-readable attributes with a confidence score.

Measured performance: 88.3% balanced accuracy (WebGPU tier; 87.6% on the CPU/WASM tier) at the fixed 0.65 confidence threshold on a 9,394-image held-out validation set spanning 43 generators (including gpt-image-1.5/2, Midjourney v7, FLUX.2, Ideogram, Firefly 3) and 6 real-photo sources, with web-realistic JPEG/resize/WebP laundering applied to 70% of images. Full per-tier/per-generator tables: docs/results/; methodology: eval/.

Model weights (one-time download at setup): https://huggingface.co/Psydoc/veridict-models

How it works

  1. A content script finds <img> elements (≥64px), prioritizes visible ones, and overlays a badge on each analyzed image. It also sets machine-readable attributes on the <img>: data-aidet-score (AI probability, 0–1), data-aidet-verdict (ai | real at the 0.65 threshold), data-aidet-status, data-aidet-source.
  2. The background service worker routes requests to an offscreen document — the inference host. It fetches image bytes (host permissions make this CORS-exempt, so the page's own images are re-fetched, never screenshotted), then:
    • runs a provenance layer first: PNG/JPEG/WebP metadata walkers detecting generator signatures (A1111, ComfyUI, Midjourney, C2PA content credentials, IPTC trainedAlgorithmicMedia, NovelAI stealth alpha-LSB). A hard metadata hit short-circuits with score ≥0.98 (measured zero false fires on 4,697 real photos);
    • otherwise decodes and runs a 5-model ONNX ensemble, gated by an early-exit cascade (a fine-tuned first-stage model answers ~98% of images alone at ~0.7s; uncertain images escalate to the full committee): Community Forensics ViT-S/384 (MIT) — stock plus a laundering-hardened fine-tune on OpenFake-train/CF-Small/COCO (training scripts in models/finetune/), GRIP-UNINA clipdet CLIP ViT-L/14 (Apache-2.0), xRayon ConvNeXtV2 (MIT), and SAFE (Apache-2.0);
    • fuses member logits with quality-conditioned fitted stacking (JPEG-quality and resolution features modulate member trust) calibrated so the balanced-accuracy-optimal operating point sits exactly at 0.65 displayed confidence.
  3. Inference runs on WebGPU (fp16, in a dedicated worker) when available, falling back to multithreaded WASM (int8) otherwise. Preprocessing is a bit-exact TypeScript port of Pillow's resampling, verified against the Python reference by fixture tests.
  4. Model weights are downloaded once during setup (SHA-256-verified against hashes pinned in the extension package) into browser-private storage (OPFS). After that the extension is fully offline. Verdicts are cached by content hash.

Build

Requires Node.js ≥ 20 (no Python needed to build the extension).

npm ci
npm run build

The loadable extension is produced at extension/dist.

Install

  1. Open chrome://extensions, enable Developer mode (Chrome ≥ 124).
  2. Click Load unpacked and select the extension/dist directory.
  3. The setup page opens automatically: click Download models (one-time; ~985 MB on WebGPU machines, ~490 MB on CPU-only machines). After it completes, the extension needs no network access ever again.
  4. Browse. Analyzed images get badges; click the toolbar icon for a per-page summary.

To analyze file:// pages, additionally enable "Allow access to file URLs" for the extension in chrome://extensions.

Verify

npm run typecheck
npm test                      # preprocessing parity (bit-exact vs Pillow), metadata rules, ONNX logit parity
node scripts/smoke-e2e.mjs    # end-to-end in headless Chrome (asserts real model inference)
HEADED=1 node scripts/smoke-e2e.mjs   # same, headed (exercises the WebGPU tier)

Reproducing the models and the evaluation

Everything is reproducible from source; see:

  • models/ — Python scripts that convert the upstream checkpoints to ONNX (fp16/int8), verify numerical parity (fp32 ≤1e-4, fp16 ≤5e-3 probability deviation), and emit the golden fixtures used by the JS parity tests. models/upload_hf.py publishes weights + the pinned-hash download manifest.
  • eval/ — validation dataset assembly (13 public sources, seeded, quota-bounded, resume-safe), the T0–T5 web-realistic corruption protocol, scoring harnesses (score_torch.py for fast Metal scoring, score.ts for deployment-exact ONNX scoring through the same shared TypeScript preprocessing), and calibrate.py, which fits the stacking + calibration and writes shared/src/calibration.json.
  • shared/ — preprocessing, ensemble/calibration, and metadata modules imported by both the extension and the eval harness, so what is measured is what ships.

Python tooling (model conversion / eval only): uv venv .venv --python 3.12 and install eval/requirements.txt.

Privacy

Image bytes never leave the browser. There are no analytics, no remote calls after setup, and the one-time model download contacts only the public model repository.

License

MIT — see LICENSE. Model weights are downloaded at setup from their public repositories and remain under their upstream licenses (MIT / Apache-2.0; every redistributed file is listed with license and SHA-256 in models/out/*.manifest.json).

About

Chrome MV3 extension that detects AI-generated images 100% locally — WebGPU/WASM 5-model ONNX ensemble + provenance analysis, 88% balanced accuracy at a fixed 0.65 threshold. MIT.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages