Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9355867
a new list of static files for better web integration
vecna Aug 7, 2026
4ab82de
removed unused piece of code, small cleanups
vecna Aug 8, 2026
b45c872
imported new logo and started the updates
vecna Aug 9, 2026
80459df
removed old fonts, added new, svg icons, style guides
vecna Aug 10, 2026
52185b6
OOpsy, forget the TTF
vecna Aug 10, 2026
54b6ead
configured new fonts
vecna Aug 10, 2026
317f12f
updated FOLDER-DESCRIPTION
vecna Aug 10, 2026
1c17b73
updated brush to render also when the face isn't there
vecna Aug 10, 2026
4156bea
the right file is FOLDER-DESCRIPTION and not FOLDER-CONTENT
vecna Aug 10, 2026
eb91da1
removed ambiguity in FOLDER-files
vecna Aug 10, 2026
88cb674
Merge pull request #14 from vecna/fix/folder-descriptions
vecna Aug 10, 2026
0443cb3
fixed code2prompt to now fully include all the excluded folders
vecna Aug 10, 2026
5b05096
new genealogy page
vecna Aug 13, 2026
808ee17
adding of the new, perhaps definitive, style, and removal of last day…
vecna Aug 13, 2026
560b0cd
fixed homepage
vecna Aug 13, 2026
51d345a
fixed colors, trimmed SVG colors
vecna Aug 13, 2026
1194ecf
added missing fonts, license, and style
vecna Aug 13, 2026
0855539
trimmed genealogy, perhaps for the last time
vecna Aug 13, 2026
cf98cd8
removed outdated files
vecna Aug 13, 2026
8d08732
navbar and footer in all the pages
vecna Aug 13, 2026
a31b7da
the long and complete visual styleguide
vecna Aug 13, 2026
9bfff88
fixed link style and mark icon
vecna Aug 14, 2026
514b67a
added two new SVG, fixed double footer, removed old marks
vecna Aug 14, 2026
a65b51e
fixed favicons and new chip for fediverse
vecna Aug 14, 2026
8869932
small update about CTA/CHIP
vecna Aug 14, 2026
6f91f09
decoupled code2prompt + moved pages specific JS into a dedicated folder
vecna Aug 14, 2026
d10315b
improved interaction in homepage, trimmed texts
vecna Aug 15, 2026
b6d9222
revisited genealogy gfx, fixed navbar around pages + references needs…
vecna Aug 15, 2026
bc38120
the big rename from /scripts to /lab-js
vecna Aug 18, 2026
bbc97ff
added missing FOLDER-DESCRIPTION(s), fixed workshop and fediverse pages
vecna Aug 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
.DS_Store
CODE2PROMPT*.txt
C2P-*.*
node_modules
playwright-report/*
!playwright-report/FOLDER-DESCRIPTION.md
test-results/*
!test-results/FOLDER-DESCRIPTION.md
coverage/*
!coverage/FOLDER-DESCRIPTION.md
docs/*
references/.venv
!docs/FOLDER-DESCRIPTION.md
codemap/*
4 changes: 2 additions & 2 deletions JSDOC_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Node tooling exists only for tests, docs, validation, and i18n extraction.
```text
lab.html
├─ face-api.js (Vladmandic) + MediaPipe Tasks Vision
├─ scripts/main.js — application controller; exposes window.gstmxx
├─ lab-js/main.js — application controller; exposes window.gstmxx
│ ├─ camera.js — webcam stream lifecycle, 2s recording
│ ├─ engine.js — face-api 2D detection / landmarks / descriptors / matching
│ ├─ engine-3d.js — MediaPipe ImageEmbedder experimental visual-embedding path
Expand Down Expand Up @@ -73,7 +73,7 @@ with "does the modified face still match". This split is documented in the

## Module map

### Core scripts (`scripts/`)
### Core scripts (`lab-js/`)

- **`main.js`** — application entry point; initialises subsystems, dispatches the
`gstmxxReady` lifecycle event, and exposes the public API on `window.gstmxx`.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ authoring guide — kept there so they live in one place only.
## Internationalization

Runtime translations for English, Italian, and Portuguese are shipped through
`scripts/i18n.js` (a single inline message catalog + `data-i18n*` attributes +
`lab-js/i18n.js` (a single inline message catalog + `data-i18n*` attributes +
`t()` in JS). There is no `locales/` directory and no build step. Translated
pages currently include `index.html`, `lab.html`, and `loader.html`; other static
pages are English-baseline until they add `data-i18n*` bindings. See
Expand Down
36 changes: 36 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Security Policy

## Reporting a vulnerability

Report privately to **vecna@hermescenter.org**, or open a [GitHub private security advisory](https://github.com/vecna/ghostmaxxing/security/advisories/new).
Please do not open a public issue for an unpatched vulnerability.

Expect an acknowledgement within 5 working days and an assessment within 15.
We will tell you when a fix ships and credit you unless you ask us not to.

## Scope

Ghostmaxxing is a static site with no backend. Everything runs client-side and no face data is transmitted. That shapes what a vulnerability looks like here.

**In scope**

- Any path by which biometric data (camera frames, descriptors, embeddings, saved faces, thumbnails) leaves the browser or persists where a user does not expect it.
- XSS or injection in any page, particularly `report.html` — a person reading that page may be at risk, and a compromise there is a safety problem, not only a security one.
- Escape from the Ghostyle plugin sandbox into a scope that could exfiltrate data or persist across sessions.
- Weaknesses in the reporting channel described on `report.html`, including anything that could deanonymise a submitter or leak submission metadata.
- Supply-chain issues in vendored assets under `lab-js/vendor/` or `styles/vendor/`.

**Out of scope**

- The recognition pipeline failing to match, or a Ghostyle failing to defeat a match. This is the subject of the project, not a defect. See the disclaimer in the README.
- Anything related to the whistleblowing submission platform, hosted at https://raccontaci.nina.watch, should be reported at https://globaleaks.org
- Reports generated by automated scanners with no demonstrated impact.
- Missing hardening headers with no exploitable consequence on a static site.

## A note on the Ghostyle threat model

Ghostyles are arbitrary JavaScript that runs in the user's browser, and the project treats them that way deliberately — review is a maintainer reading the whole file. A malicious Ghostyle is therefore not in itself a vulnerability report. A way for a Ghostyle to reach beyond its documented surface **is**.

## Machine-readable pointer

`/.well-known/security.txt` (RFC 9116) points here.
126 changes: 104 additions & 22 deletions about.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vision & About — Ghostmaxxing</title>
<link rel="icon" type="image/svg+xml" href="/images/ghostmaxxing-favicon.svg">
<link rel="icon" type="image/svg+xml" href="/images/logo/mark-onlight.svg">
<meta name="description"
content="Ghostmaxxing is a browser-based public research platform for testing face-recognition camouflage, running workshops, and investigating real-world biometric surveillance." />
<meta property="og:title" content="Vision & About - Ghostmaxxing" />
Expand All @@ -16,30 +16,57 @@
<meta name="twitter:title" content="Vision & About - Ghostmaxxing" />
<meta name="twitter:description" content="A public lab for testing face-recognition camouflage." />
<meta name="twitter:image" content="/images/social-card.svg" />
<link rel="stylesheet" href="styles/pages.css" />
<link rel="stylesheet" href="styles/content-pages.css" />
<link rel="stylesheet" href="/styles/styles.css" />
<link rel="stylesheet" href="/styles/pages.css" />
<link rel="stylesheet" href="/styles/content-pages.css" />
</head>

<body>

<!-- ===== SITE HEADER — canonical. Byte-identical on every page. =========
Only two things may differ per page: aria-current="page" on the link to
the current page, and the optional .gm-site-nav__extra slot.
Styling: styles/chrome.css. Behaviour: lab-js/nav.js.
==================================================================== -->
<header class="gm-site-header">
<a class="gm-site-wordmark" href="/" aria-label="Ghostmaxxing homepage">
<img class="gm-site-wordmark__mark" src="/images/logo/mark-color.svg" width="40" height="40" alt="" aria-hidden="true" />
<span class="gm-site-wordmark__text">
<span class="gm-site-wordmark__title">Ghostmaxxing</span>
<span class="gm-site-wordmark__sub">A public lab for testing camouflage</span>
</span>
</a>
<nav class="gm-site-nav" aria-label="Primary">
<a class="gm-site-chip" href="/fediverse.html">in the Fediverse</a>
<div class="gm-site-nav__group">
<button class="gm-site-nav__trigger" aria-expanded="false" aria-controls="gmSiteMenu">Know more <span aria-hidden="true">&#9662;</span></button>
<div class="gm-site-menu" id="gmSiteMenu">
<div>
<p class="gm-site-menu__kicker">Informative</p>
<ul>
<li><a href="/about.html" aria-current="page">Vision &amp; about</a></li>
<li><a href="/genealogy.html">The genealogy of the read</a></li>
<li><a href="/report.html">Report a deployment</a></li>
<li><a href="/workshops.html">Workshops</a></li>
</ul>
</div>
<div>
<p class="gm-site-menu__kicker">Technology</p>
<ul>
<li><a href="/lab.html">Open the lab &#8599;</a></li>
<li><a href="/ghostyle-transfer.html">Ghostyle transfer</a></li>
<li><a href="/references/">References archive</a></li>
<li><a href="/docs/">Docs</a></li>
<li><a href="https://github.com/vecna/ghostmaxxing">Code</a></li>
</ul>
</div>
</div>
</div>
<a class="gm-site-cta" href="/report.html">Leak to us &#8599;</a>
</nav>
</header>
<main class="editorial-homepage content-page editorial-homepage--svg-footer-band">
<div class="editorial-homepage__shell">
<header class="editorial-homepage__header">
<a class="wordmark" href="index.html" aria-label="Ghostmaxxing homepage">
<span class="wordmark__main">
<img class="wordmark__mark" src="images/ghostmaxxing-mark.svg" alt="" aria-hidden="true" />
<span class="wordmark__title">Ghostmaxxing</span>
</span>
<span class="wordmark__subtitle">
A public lab for testing face-recognition camouflage
</span>
</a>

<nav class="editorial-homepage__nav" aria-label="Project navigation">
<a class="navlink" href="/references/" rel="noopener noreferrer">Research References</a>
<a class="navlink" href="about.html" aria-current="page">Vision &amp; About</a>
<a class="cta-inline" href="report.html">How to <i>leak</i> to us<span aria-hidden="true">↗</span></a>
</nav>
</header>

<section class="content-page__header-area" aria-labelledby="page-title">
<span class="content-page__kicker">Vision &amp; About</span>
Expand All @@ -55,7 +82,7 @@ <h1 id="page-title">Make the machine-readable face <i>contestable</i>.</h1>
</section>

<div class="content-page__layout">
<article class="content-page__main">
<article class="content-page__main gm-prose">
<section class="content-section" id="workshop-assistant">
<h2>Workshop assistant.</h2>
<p>
Expand Down Expand Up @@ -287,8 +314,63 @@ <h2>On this page</h2>
</div>
</div>

<div class="camera-band" aria-hidden="true"></div>
</main>

<!-- ===== SITE FOOTER — canonical. Byte-identical on every page. =========
Pyre band, soil edge, link row. Replaces the .camera-band div, which
pointed at images/homepage-camera-band.svg — not in the repo, so it only
ever painted a faint gradient. The camera icons are INLINE <svg>: the
files in images/icons/ are class-driven and render black through <img>.
==================================================================== -->
<footer class="gm-site-footer">
<div class="gm-site-footer__pyre" data-mode="full">
<img src="/images/motifs/pyre.svg" alt="" aria-hidden="true" />
</div>
<img class="gm-site-footer__edge" src="/images/motifs/soil-edge.svg" alt="" aria-hidden="true" />
<div class="gm-site-footer__row">
<div class="gm-site-footer__cams">
<svg class="cam" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<path class="cam-mount" d="M6,29 H94" stroke-width="7"></path>
<path class="cam-shell" d="M20,29 A30,30 0 0 0 80,29 Z"></path>
<circle class="cam-lens" cx="50" cy="44" r="15"></circle>
<circle class="cam-iris" id="iris-dome" cx="50" cy="44" r="6.6"></circle>
<circle class="cam-glint" cx="45.5" cy="39.5" r="2.55"></circle>
</svg>
<svg class="cam" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<path class="cam-mount" d="M80,26 V92" stroke-width="6"></path>
<path class="cam-mount" d="M80,30 H44" stroke-width="6"></path>
<path class="cam-mount" d="M52,30 V40" stroke-width="5"></path>
<rect class="cam-shell" x="10" y="40" width="72" height="30" rx="7"></rect>
<rect class="cam-panel" x="54" y="47" width="22" height="16" rx="3"></rect>
<g class="cam-dot"><circle cx="60" cy="51" r="2"></circle><circle cx="70" cy="51" r="2"></circle><circle cx="60" cy="59" r="2"></circle><circle cx="70" cy="59" r="2"></circle></g>
<circle class="cam-lens" cx="32" cy="55" r="12"></circle>
<circle class="cam-iris" id="iris-street" cx="32" cy="55" r="5.3"></circle>
<circle class="cam-glint" cx="28.4" cy="51.2" r="2"></circle>
</svg>
<svg class="cam" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<path class="cam-mount" d="M8,44 L2,32 M92,44 L98,32" stroke-width="5"></path>
<path class="cam-shell" d="M50,45 C65,25 90,25 90,45 C90,65 65,65 50,45 C35,25 10,25 10,45 C10,65 35,65 50,45 Z" stroke-linecap="round"></path>
<path class="cam-glare" d="M22,52 L34,38 M29,53 L37,44"></path>
<path class="cam-glare" d="M66,52 L78,38 M73,53 L81,44"></path>
<circle class="cam-iris cam-iris--void" id="iris-glasses-l" cx="28" cy="45" r="9"></circle>
<circle class="cam-iris cam-iris--void" id="iris-glasses-r" cx="72" cy="45" r="9"></circle>
</svg>
<svg class="cam" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<path class="cam-mount" d="M45,30 V12 M32,12 H58" stroke-width="5"></path>
<rect class="cam-shell" x="16" y="36" width="66" height="34" rx="5"></rect>
<path class="cam-mount" d="M12,30 H74 L84,40" stroke-width="5"></path>
<circle class="cam-lens" cx="60" cy="51" r="14"></circle>
<circle class="cam-iris" id="iris-bullet" cx="60" cy="51" r="6.2"></circle>
<circle class="cam-glint" cx="55.8" cy="46.8" r="2.4"></circle>
</svg>
</div>
<div class="gm-site-footer__links">
<a href="/docs/">Technical documentation</a>
<a href="https://github.com/vecna/ghostmaxxing">Code</a>
<a href="/loader.html">Video Loader</a>
</div>
</div>
</footer>
</body>

</html>
Binary file removed apple-touch-icon.png
Binary file not shown.
Empty file added codemap/.keep
Empty file.
Loading
Loading