Digital Dignity: Am I in P*rn?
Eine Next.js-Web-App, mit der Menschen herausfinden können, ob ihr Gesicht ohne ihre Zustimmung in P*rnos im Netz auftaucht. Ehrenamtliche Arbeit für Digital Dignity.
Betroffene nicht einvernehmlicher intimer Aufnahmen hatten keinen sicheren Weg, nach ihrem eigenen Gesicht zu suchen, und die Suche selbst durfte nicht zu einem neuen Werkzeug für Missbrauch werden.
- Rolle:
- Frontend-Entwickler (ehrenamtlich); Frontend weitgehend allein neu gebaut
- Stack:
- Next.js · React · Node.js · Bootstrap · GitHub CI/CD
- Zeitraum:
- 2023–2024
- veröffentlicht:
Problem und Rahmenbedingungen
Digital Dignity, eine Organisation aus Köln, betreibt Am I in P*rn?, einen Dienst, mit dem Menschen prüfen können, ob ihr Gesicht in p*rnografischem Material auftaucht, das ohne ihre Zustimmung veröffentlicht wurde, und der ihnen anschließend hilft, es entfernen zu lassen. Ich bin 2023 als ehrenamtlicher Frontend-Entwickler dazugekommen, neben meinem Hauptjob, und bis Ende 2024 geblieben.
Das Produkt bewegt sich in einem Geflecht aus Rahmenbedingungen, das jede Frontend-Entscheidung geprägt hat. Um nach dem eigenen Gesicht zu suchen, muss man sein Gesicht einreichen; das Suchwerkzeug selbst darf also nicht zum Instrument für Missbrauch werden, und es darf die sensibelsten biometrischen Daten, die es gibt, nicht horten. Hinzu kommt: Nach EU-Regeln gilt das Anzeigen des gefundenen Materials als Verbreitung von Inhalten für Erwachsene, die Plattform darf ihre eigenen Suchergebnisse also nicht anzeigen. Und die Menschen, die sie nutzen, befinden sich per Definition in einer belastenden Lage, und sie sind meist auf dem Smartphone unterwegs.
Das Team war klein und vollständig ehrenamtlich: Entwickler unter der Anleitung einer Projektleitung, keine Designer. Die meisten aus meinem Frontend-Team waren vor allem zum Lernen dazugekommen, und so landete ein Großteil des Neubaus bei mir, abends und an Wochenenden.
Architektur
Die ursprüngliche Website war schlichtes HTML/CSS/JS, geschrieben von den Backend-Entwicklern. Ich habe das Frontend als responsive Next.js-Anwendung neu gebaut, angebunden an die Node.js-Dienste des Teams, mit einer CI/CD-Pipeline auf GitHub und Mobile-first entworfen: Die Frontkamera eines Smartphones ist das wichtigste Aufnahmegerät.
Die Suche selbst arbeitet mit Gesichtsgeometrie: Der Browser nimmt eine kurze Live-Kamerasequenz auf, ein eigener Dienst im Backend wandelt das Gesicht in eine Vektordarstellung um, und dieser Vektor, nicht das Bild, wird gegen indexierte Medien abgeglichen. Jedes aufgenommene Bild wird direkt nach der Vektorisierung verworfen. Die Ergebnisse kommen per E-Mail: zuerst eine offizielle Benachrichtigung, und bei Treffern folgen Links von einer anonymen Adresse zu kurzlebigen externen Ansichtsseiten, sodass die Plattform das Material selbst nie ausliefert. Bestätigt die Person, dass sie es ist, geht der Fall an eine Partnerkanzlei, die eine formelle Löschaufforderung stellt. Die Entscheidungen dahinter stehen im Entscheidungsprotokoll unten, jede mit der Alternative, gegen die sie sich durchgesetzt hat.
Ergebnisse
Aus einer statischen, von Hand gebauten Website wurde eine responsive Next.js-Anwendung, Mobile-first, mit einem missbrauchsresistenten Aufnahmeablauf, ohne jede Speicherung von Bildern und mit anwaltlich geprüfter DSGVO-Konformität, gebaut in ehrenamtlicher Zeit an Abenden und Wochenenden.
Die Grenzen gehören klar benannt: Die neu gebaute Plattform war noch nicht live, als ich ging; andere Teile des Systems brauchten noch Arbeit, und mein neuer Arbeitsvertrag schloss Nebentätigkeiten während der Probezeit aus. Das Projekt ist seitdem unter dem Namen Digital Dignity auf digitaldignity.io neu gestartet, und die Suche ist inzwischen weltweit verfügbar. Sprechen kann ich nur für das Frontend, wie es bei der Übergabe stand; was danach live ging, ist die Arbeit des Teams, nicht meine.
Lehren
Zwei Dinge bleiben. Erstens das Denken gegen Missbrauch: Die interessantesten Frontend-Probleme waren hier nicht visuell, sondern adversarial. Jeder Eingabeweg musste darauf geprüft werden, wie jemand mit bösen Absichten ein Werkzeug zur Unterstützung Betroffener gegen eine andere Person wenden könnte. Die Umgehung über die Galerie der nativen Kamera zu schließen ist ein winziges Detail, das keine Feature-Liste je zeigen würde, und genau die Art Detail, auf die es ankommt.
Zweitens der Stack: Die intensive Arbeit mit React und Next.js hat meine Framework-Vorlieben geklärt. Das schnelllebige Ökosystem und die konkurrierenden Konventionen machten mir das Bauen schwerer als bei Vue, und für ein eigenes Projekt würde ich weiterhin zuerst zu Vue greifen, eine Einschätzung, die ich nur ehrlich treffen konnte, weil ich mit React etwas Echtes gebaut habe.
Zentrale Entscheidungen
01 Aufnahme: nur die eingebettete Live-Kamera
Eine Kameraoberfläche in der Seite mit Live-Aufnahme.
Beides hätte erlaubt, ein heruntergeladenes Foto einer anderen Person einzureichen; nur die eingebettete Oberfläche beschränkt die Suche auf die eigene Person.
Auf Mobilgeräten bietet die native Kamera auch die Galerie an, und genau diese Umgehung mussten wir schließen. Der Aufnahmeablauf fordert die Person außerdem auf, ihren Gesichtsausdruck zu ändern (Mund oder Augen öffnen und schließen), damit die Geometrieprüfungen im Backend ein lebendes Gesicht von einem Foto eines Fotos unterscheiden können.
verworfen: Datei-Upload · Die native Kamera-App des Geräts
02 Keine Speicherung von Bildern
Jedes aufgenommene Bild direkt nach der Vektorisierung verwerfen.
Ein Speicher voller Gesichter wäre ein rechtliches und finanzielles Risiko, das keine datenschutzorientierte gemeinnützige Organisation tragen sollte; die Lebendprüfung bei jedem Besuch zu wiederholen ist der vertretbare Preis.
Anwälte haben die DSGVO-Konformität der App geprüft; erst das sofortige Verwerfen macht den übrigen Ablauf vertretbar.
verworfen: Aufnahmen speichern, damit wiederkehrende Nutzer die erneute Prüfung überspringen können
03 Zustellung der Ergebnisse
Benachrichtigung per E-Mail, mit Links von einer anonymen Adresse zu kurzlebigen externen Ansichtsseiten.
Nach EU-Regeln gilt das Anzeigen des gefundenen Materials als Verbreitung von Inhalten für Erwachsene; die Plattform darf ihre Funde daher nicht auf der eigenen Domain zeigen.
Die offizielle Adresse stellt die Mitteilung zu; die Links zu den flüchtigen Ansichtsseiten kommen getrennt von einer anonymen Adresse.
verworfen: Treffer direkt in der App anzeigen
04 Stack: Neubau auf Next.js
Die von Hand gebaute HTML/CSS/JS-Website als Next.js-App neu aufbauen.
Das Team wollte etwas Zugänglicheres, Leistungsfähigeres und Sichereres als das Original, und das Framework war eine bewusste Teamentscheidung, für mich zugleich die Gelegenheit, einen Stack zu lernen, den ich noch nicht kannte.
verworfen: Die ursprüngliche statische Website weiter flicken
Kennzahlen
| Kennzahl | Wert | Status |
|---|---|---|
| Gespeicherte Gesichtsbilder | 0 | eigene Angabe |
Eigene Angaben: So entworfen: Jede Aufnahme wird direkt nach der Vektorisierung verworfen; die DSGVO-Konformität haben die Anwälte des Projekts geprüft