Ghostmaxxing is a static, browser-side Web AR laboratory for designing and testing face-obfuscation overlays against face-detection and face-recognition pipelines.
The project combines webcam capture, face-api.js, MediaPipe Tasks Vision, canvas rendering, local descriptor storage, and a plugin system for custom Ghostyles: 2D or 3D face overlays that can be tested against recognition behavior in real time.
Primary links:
- Live project root: https://sindacato.nina.watch/ghostati/
- Browser app: ghostati.html
- Source code: github.com/vecna/ghostati
- Ghostyle gallery / distribution site: ghostyles.vecna.eu
- Generated API docs: docs/
- Legacy docs page: ghostati-docs.html
- Test coverage: coverage/
- Project context page: sindacato.nina.watch/it/iniziative/ghostati
- Sitemap: sitemap.xml
- Reference dataset: REFERENCES.json
- Reference-update prompt: PROMPT-REFERENCES-UPDATE.txt
Central field-reporting resource: if you know of a place where facial recognition is being deployed, tested, procured, or hidden in public-space infrastructure, use the NINA submission node: Raccontacelo. Reports about supplier, technology, data access, deployment context, limits, and abuses are project inputs, not side notes.
webcam ──► detector ──► landmarks ──► overlay renderer
│ │ │
└──── baseline face DB ◄──┴──── compare ◄──┘
The app is designed around a simple experimental loop:
- Start the webcam in a modern browser.
- Load face-detection and landmark models.
- Save a local baseline descriptor for a consenting test face.
- Apply a Ghostyle overlay to the live video/canvas layer.
- Re-run detection and recognition against the saved descriptor.
- Observe whether the pipeline still detects the face, extracts landmarks, and matches the baseline.
Core capabilities:
- live webcam setup and teardown through
scripts/camera.js; - face detection, landmarks, descriptors, and match orchestration through
scripts/engine.js; - 3D/MediaPipe loop support through
scripts/mediapipe-loop.jsandscripts/engine-3d.js; - bounding-box overlays through
scripts/bbox-overlay.js; - dynamic Ghostyle loading through
scripts/ghostyles-manager.js; - 3D plugin loading through
scripts/plugins3d-loader.js; - IndexedDB-backed local state through
scripts/db.js; - DOM and UI bindings through
scripts/dom.js,scripts/main.js, andscripts/ghostati-mobile-ui.js; - image/makeup export helpers through
scripts/export-makeup.js; - landing-page animation through
scripts/index-effect.js.
ghostati.html
├─ @vladmandic/face-api
├─ @mediapipe/tasks-vision
├─ scripts/main.js
│ ├─ camera.js
│ ├─ engine.js
│ ├─ db.js
│ ├─ dom.js
│ └─ ghostyles-manager.js
├─ ghostyles.json
└─ ghostyles/*.js
The project is a static web app: there is no production build step required to open the interface locally. The browser loads HTML, CSS, JavaScript modules, model assets, and plugin manifests.
Important local entry points:
index.html— public landing page with links to code, docs, coverage, Ghostyles, project context, and the reporting node.lab.html— translated main webcam/AR application.loader.html— translated internal MP4 loader for repeatable 2D/3D video tests.ghostati.html— legacy main webcam/AR application entry point.ghostyles.json— Ghostyle manifest.JSDOC_README.md— concise generated-docs overview.REFERENCES.json— curated technical/cultural reference set.
Ghostmaxxing currently ships runtime translations for English, Italian, and Portuguese through scripts/i18n.js. The translated browser pages are:
index.html— homepage and public navigation.lab.html— main camera lab, settings, drawers, controls, status labels, and runtime logs.loader.html— internal MP4 video loader, language switcher, static interface labels, model status, and loader activity logs.
Other static pages such as about.html, report.html, workshop/tutorial pages, generated docs, coverage, and reference pages are still English-baseline unless they add data-i18n* bindings and catalog keys.
Runtime external dependencies visible from the HTML/config layer:
- Google Fonts / Google Fonts static assets
- Landing-page Google Fonts CSS
- jsDelivr CDN
@vladmandic/face-api- face-api.js model weights
- MediaPipe Tasks Vision
- MediaPipe Face Landmarker model
- MediaPipe Image Embedder model
For workshops or higher-risk demos, prefer self-hosting model and library assets instead of relying on third-party CDNs.
clone ──► install dev deps ──► static server ──► browser + webcam
Clone the repository:
git clone https://github.com/vecna/ghostati.git
cd ghostatiInstall development dependencies:
npm installServe the directory with any local static server:
npx http-server .
# or
python3 -m http.server 8000Open the app:
http://localhost:8000/ghostati.html
Open the landing page:
http://localhost:8000/
landmarks + box + canvas context
│
▼
ghostyle module
│
▼
live overlay + diagnostic pass
A Ghostyle is a JavaScript module that draws an overlay anchored to a detected face. It can be local or loaded through a manifest.
Start from ghostyles/00-template.js, then add the file to ghostylist.json. Existing 2D examples include:
ghostyles/graphic-liner.jsghostyles/smokey-eyes.jsghostyles/blush-lift.jsghostyles/lip-tint.jsghostyles/soft-contour.jsghostyles/stage-mask.jsghostyles/splash.js
A minimal 2D plugin shape:
/**
* @name Example Ghostyle
* @engine faceapi
*/
export function onInit() {
return 'loaded';
}
export function onDraw(ctx, landmarks, box) {
ctx.save();
// Draw against landmarks and detection box here.
ctx.restore();
}
export function onClear(ctx) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}3D/MediaPipe-oriented examples live in:
Register them in ghostylist3d.json.
unit tests ──► coverage
e2e tests ──► browser flows
jsdoc ──► docs/
Package scripts:
npm run test:unit
npm run test:unit -- --coverage
npm run test:e2e
npm run docsTesting stack:
- Vitest for unit tests;
@vitest/coverage-v8for coverage;- Playwright for browser-level tests;
- JSDOM and node-canvas for DOM/canvas test fixtures;
- JSDoc with
clean-jsdoc-themefor generated documentation.
Relevant test directories:
browser storage
├─ descriptors
├─ preferences
└─ test state
external network
├─ fonts
├─ CDN libraries
└─ model weights
The app is designed to keep biometric test data local to the browser interface. Face descriptors and related state are stored locally, not posted to a central server by the default app flow.
Technical caveats:
- webcam access is controlled by the browser permission model;
- local descriptors may persist in IndexedDB/local browser storage until cleared;
- screenshots, recordings, and exports should be treated as sensitive biometric-adjacent material;
- CDN-loaded libraries and model files still create external network requests;
- detection failure, landmark instability, and match failure are different outcomes and should not be collapsed into “anonymity”;
- a Ghostyle that affects this browser pipeline may not affect another face-recognition system.
Use consenting test subjects. Do not represent experimental overlays as operational safety guarantees.
observe ──► document ──► submit ──► update resistance research
Ghostmaxxing is also connected to a field-reporting workflow. The landing page now treats the NINA reporting node as a central project resource:
Raccontacelo: segnala un possibile uso di riconoscimento facciale nello spazio pubblico
Useful report details include:
- location and institutional context;
- supplier or vendor name;
- visible hardware or software clues;
- procurement documents, signage, screenshots, or public records;
- who appears to access the data;
- retention, oversight, and abuse risks;
- whether the system is detection-only, identification, verification, watchlist matching, analytics, or unclear.
The point is to turn deployments into inspectable evidence: claims, vendors, interfaces, procurement, sensors, data flows, and affected communities.
REFERENCES.json ──► timeline / exhibition / research context
PROMPT-REFERENCES-UPDATE.txt ──► repeatable curation rules
REFERENCES.json is a curated dataset of artistic, research, and activism-adjacent references around face obfuscation, adversarial appearance design, makeup-based attacks, physical-world adversarial vision, and sensor disruption.
The update protocol in PROMPT-REFERENCES-UPDATE.txt keeps the file deduplicated, sorted, and stable. It requires canonical links, local preview-image paths, stable slugs, and a closeness score from 1 to 100.
Current reference links:
- Human-Imperceptible Physical Adversarial Attack for NIR Face Recognition Models — Songyan Xie, Jinghang Wen, Encheng Su et al., 2025 ·
research· closeness22 - Accessorize in the Dark: A Security Analysis of Near-Infrared Face Recognition — Amit Cohen, Mahmood Sharif, 2024 ·
research· closeness22 - DAZZLE — Michelle Tylicki, Lauri Love, 2023 ·
activism· closeness100 - Physical-World Optical Adversarial Attacks on 3D Face Recognition — Yanjie Li, Yiquan Li, Xuelong Dai et al., 2023 ·
research· closeness30 - The Camera-Shy Hoodie — Mac Pierce, 2023 ·
artistic· closeness20 - Shadows can be Dangerous: Stealthy and Effective Physical-world Adversarial Attack by Natural Phenomenon — Yiqi Zhong, Xianming Liu, Deming Zhai et al., 2022 ·
research· closeness35 - The Dazzle Club — Evie Price, Emily Roderick, Georgina Rowlands et al., 2021 ·
activism· closeness96 - Adv-Makeup: A New Imperceptible and Transferable Attack on Face Recognition — Bangjie Yin, Wenxuan Wang, Taiping Yao et al., 2021 ·
research· closeness95 - Adversarial Attacks against Face Recognition: A Comprehensive Study — Fatemeh Vakhshiteh, Ahmad Nickabadi, Raghavendra Ramachandra, 2020 ·
research· closeness82 - Breaking certified defenses: Semantic adversarial examples with spoofed robustness certificates — Amin Ghiasi, Ali Shafahi, Tom Goldstein, 2020 ·
research· closeness35 - VLA: A Practical Visible Light-based Attack on Face Recognition Systems in Physical World — Meng Shen, Zelin Liao, Liehuang Zhu et al., 2019 ·
research· closeness78 - Adversarial Robustness Toolbox v1.0.0 — Maria-Irina Nicolae, Mathieu Sinn, Minh Ngoc Tran et al., 2018 ·
research· closeness55 - DPatch: An Adversarial Patch Attack on Object Detectors — Xin Liu, Huanrui Yang, Ziwei Liu et al., 2018 ·
research· closeness40 - ShapeShifter: Robust Physical Adversarial Attack on Faster R-CNN Object Detector — Shang-Tse Chen, Cory Cornelius, Jason Martin et al., 2018 ·
research· closeness38 - Adversarial Generative Nets: Neural Network Attacks on State-of-the-Art Face Recognition — Mahmood Sharif, Sruti Bhagavatula, Lujo Bauer et al., 2017 ·
research· closeness90 - Adversarial Patch — Tom B. Brown, Dandelion Mané, Aurko Roy et al., 2017 ·
research· closeness50 - Accessorize to a Crime: Real and Stealthy Attacks on State-of-the-Art Face Recognition — Mahmood Sharif, Sruti Bhagavatula, Lujo Bauer et al., 2016 ·
research· closeness92 - HyperFace — Adam Harvey, 2016 ·
artistic· closeness92 - Adversarial Manipulation of Deep Representations — Sara Sabour, Yanshuai Cao, Fartash Faghri et al., 2015 ·
research· closeness45 - CV Dazzle — Adam Harvey, 2010 ·
artistic· closeness100
small patch
## Recent changes
- `85f9100` internationalization added, three languages
- `697c972` JSdoc improvements
- `1a49dea` added condition for face not found during composite analysis
- `3b32d40` deleted some dead code and improved UT
- `b09f30a` removal of duplicated code