Sicherheit
Unser Sicherheitsmodell in einem Satz: Es gibt nichts auf einem Server, das angegriffen werden könnte. Alles Folgende ist über Ihre DevTools nachprüfbar.
Architektur
Der Generator ist eine statische Single-Page-Anwendung, die von Cloudflare Pages bereitgestellt wird: keine Benutzerkonten, keine Authentifizierung und kein Backend-Code-Pfad irgendwo im Generierungsablauf. Jede QR-Generierungs-, Kodierungs-, Scan- und Rendering-Operation läuft vollständig in Ihrem Browser. Ein kleiner serverloser Endpunkt steht daneben und wird hier genannt statt versteckt: /api/contact (das Kontaktformular, das speichert, was Sie einreichen, in Cloudflare D1, und es uns per E-Mail sendet). Er wird nicht aufgerufen, während Sie einen QR-Code erstellen; die URL-Sicherheitsprüfung ist ein separates Produkt unter check.qr.abundera.ai. QR-Code auf Sicherheit prüfen
Bedrohungsmodell
Da der Generator keine Benutzerdaten erfasst, speichert oder überträgt (die beiden Endpunkte oben verarbeiten nur, was Sie ihnen ausdrücklich schicken), gelten die häufigsten Web-App-Bedrohungen — Credential-Diebstahl, Datenbankeinbruch, Session-Hijacking, serverseitige Injection — für ihn nicht. Die verbleibende Angriffsfläche ist das statische Asset-Bundle (HTML, CSS, JavaScript), das von unserem Ursprung bereitgestellt wird. Wir entwickeln unter der Annahme:
- Kompromittierung des Ursprungs: Ein Angreifer ersetzt eines unserer gebündelten Assets durch ein bösartiges. Die unten beschriebene CSP begrenzt den Explosionsradius; Cache-Buster-Token erleichtern den Rollback auf eine bekannte gute Version.
- Benutzereingaben: QR-Payloads, vCard-Namen, WLAN-Passwörter, CSV-Zeilen im Batch-Betrieb, gescannte Bildinhalte. Jeder Eingabepfad wird als nicht vertrauenswürdig behandelt, wenn er wieder im DOM gerendert wird.
- Vom Benutzer bereitgestellte Bilder: vCard-Foto-URLs und Logo-Uploads. Bilder werden in ein Canvas gerendert, nie als rohes Markup in das DOM eingebettet.
- Browser-Erweiterungen von Drittanbietern: außerhalb des Geltungsbereichs. Wenn eine Erweiterung in Ihrem Browser die Berechtigung hat, jede Seite zu modifizieren, kann sie auch unsere modifizieren. Unsere Garantien gelten, wenn die Seite unverändert geladen wird.
Content Security Policy — nach Direktive
Die untenstehende Richtlinie wird beim Build dieser Seite aus der ausgelieferten _headers-Datei gelesen, sie kann also nicht von dem abweichen, was die Edge sendet. Prüfen Sie sie in den Antwort-Headern jeder Anfrage.
Content-Security-Policy:
default-src 'self';
script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com;
worker-src 'self' blob:;
style-src 'self' 'unsafe-inline' https://abundera.ai;
font-src 'self';
img-src 'self' data: blob: https:;
connect-src 'self' https: https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'Was jede Direktive uns erlaubt zu tun und wo sie Kompromisse eingeht:
default-src 'self'— der harte Boden. Alles, was wir nicht explizit lockern, bleibt same-origin.script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com— kein inline<script>, keineval().abundera.aiist unsere eigene übergeordnete Domain und liefert ein einziges gemeinsames Skript, den Sprachwähler.challenges.cloudflare.comist das Turnstile-Widget, das nur auf /contact/ verwendet wird.'wasm-unsafe-eval'wird durch den WebAssembly-Kompilierungspfad unserer QR-Encoder-Bibliothek benötigt; es erlaubt NICHT traditionelleseval(). Unsere eigene Pre-Deploy-Prüfung scannt jede HTML-Seite nach Inline-Skripten und bricht den Build ab.style-src 'self' 'unsafe-inline'— ein echtes Zugeständnis. Unsere QR-Vorschau berechnet Farben auf Pixelebene inline (Style-Attribute auf einzelnen Modulen). Eine Hash-basierte Allowlist würde funktionieren, würde aber bei jeder Style-Aktualisierung ohne Deploy fehlschlagen. Kompromiss: Wir akzeptieren die leicht schwächere Style-Richtlinie; Styling kann ohnehin keine Daten exfiltrieren (CSS hat keineconnect-src-Reichweite).img-src 'self' data: blob: https:—data:für inline QR-Renderings,blob:für Export-Download-URLs,https:für vom Benutzer bereitgestellte vCard-Foto- und Avatar-URLs. Vom Benutzer bereitgestellte URLs werden nie ausgeführt, nur gerendert. Beachten Sie, dass diese Direktive auch ein ausgehender Kanal ist: jedes Skript, das auf der Seite läuft, könnte ein Bild von jedem HTTPS-Host anfordern und Daten in die URL packen. Wir akzeptieren das, weil die Funktion es braucht, und sagen das hier, statt die Richtlinie als hieb- und stichfest zu beschreiben.connect-src 'self' https: https://challenges.cloudflare.com— die Direktive, die man genau lesen sollte.https:ist eine Schema-Quelle: sie erlaubtfetch(), XMLHttpRequest, WebSocket über TLS, EventSource undsendBeacon(), jeden HTTPS-Ursprung zu erreichen, nicht nur die, die Sie eingetippt haben. Sie ist da, damit das vCard-Foto-Feld und die URL-Sicherheitsprüfung eine eingefügte Adresse abrufen können. Sie verhindert keine Exfiltration durch ein bösartiges Skript; das tut keine CSP-Direktive, sobald das Skript bereits als wir läuft. Was Exfiltration verhindert, ist, dass unser ausgelieferter Code keine solchen Anfragen stellt, was Sie im Netzwerk-Tab beobachten können.frame-src 'self' https://challenges.cloudflare.com— nur das Turnstile-Widget darf eingebettet werden.frame-ancestors 'none'— keine andere Website kann uns einbetten. Verhindert Clickjacking.base-uri 'self'— ein bösartig injiziertes<base>-Tag kann relative URLs nicht zum Ursprung eines Angreifers umleiten.form-action 'self'— jedes injizierte Formular kann nur an unseren Ursprung posten. Das Kontaktformular ist das einzige Formular, das irgendwohin sendet.
Was CSP nicht kann
CSP begrenzt, von wo der Browser Code lädt. Es prüft nicht, was geladener Code tut. Wäre unser Ursprung kompromittiert, der erste Punkt im Bedrohungsmodell, würde das Skript des Angreifers mit denselben Rechten laufen wie unseres, einschließlich der oben genannten connect-src- und img-src-Erlaubnisse. Unsere Verteidigung dagegen liegt vor CSP: Deployments laufen über ein einziges Cloudflare-Konto mit eingeschränkten Tokens, Asset-Dateinamen sind inhaltsbasiert gehasht, sodass eine ausgetauschte Datei jede URL ändert, die auf sie verweist, und der Service Worker cached nur same-origin GET-Antworten. Das Manifest beschreibt die Website, wie sie ausgeliefert wird. Es ist keine Behauptung, dass keine Webseite jemals irgendwo Daten senden könnte, und wir möchten lieber, dass Sie uns an der engeren, überprüfbaren Aussage messen.
Für /bio/* (gelockertes img-src für vom Benutzer bereitgestellte Avatare) und /embed/* (gelockertes frame-ancestors für absichtliches Einbetten) gelten andere CSP-Richtlinien. Beide sind in site/_headers dokumentiert.
Transport- und Framing-Header
- HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload— 1 Jahr, alle Subdomains, berechtigt für die HSTS-Preload-Liste. Downgrades auf HTTP werden von konformen Browsern abgelehnt. - X-Frame-Options: DENY — redundant mit CSP
frame-ancestors, wird für ältere Browser-Abdeckung beibehalten. - X-Content-Type-Options: nosniff — verhindert MIME-Verwechslungsangriffe.
- Referrer-Policy: strict-origin-when-cross-origin — ausgehende Link-Klicks geben den Ursprung, aber nicht den Pfad preis.
- Permissions-Policy:
camera=(self), microphone=(), geolocation=()— Kamera nur für unseren eigenen Scanner erlaubt; Mikrofon und Standort explizit verweigert, auch wenn eingebettet.
Service Worker
Unser Service Worker (site/sw.js) cached nur same-origin Assets. Der fetch-Handler lehnt Cross-Origin-Anfragen und Nicht-GET-Methoden explizit ab — Sie können die Logik in /sw.js nachlesen (der Quelltext bleibt unminifiziert genug, um ihm zu folgen). Cache-Schreibvorgänge sind in event.waitUntil() eingebettet, damit sie nicht mitten in einer Navigation verworfen werden können.
Eingabe-Sanitisierung
Jeder Rendering-Pfad, der Benutzereingaben akzeptiert, behandelt sie als nicht vertrauenswürdigen Text:
- QR-Payload-Vorschauen verwenden
textContent, nichtinnerHTML. - Share-Ziele (Zwischenablage,
navigator.share()) übergeben Benutzertext als String, nie als Markup. - SVG-Exporte werden von unserer Encoder-Bibliothek generiert; Benutzerinhalte werden base64-kodiert in
<image>xlink:href, nicht als SVG-Elemente injiziert. - Druckvorschauen verwenden eine Blob-URL, nicht
document.write(). - localStorage-Parsing ist in
try/catcheingebettet — ein korrupter Eintrag ergibt einen frischen leeren Standard, nie eine Ausnahme, die sich in einen aktiven Code-Pfad entfalten könnte. - Vom Benutzer bereitgestellte URLs, die als "Link öffnen"-Schaltflächen angezeigt werden, sind auf
http(s)://beschränkt —javascript:- unddata:-Schemata werden abgelehnt.
Cross-Origin-Bildabruf
Wenn ein Benutzer eine https:-URL als vCard-Foto oder Logo einfügt, ruft der Browser sie gemäß CORS und der img-src-Allowlist unserer CSP ab. Das Bild wird in ein Canvas gerendert. Es wird nie zu aktivem DOM, wird nie als Code ausgeführt und erreicht nie unseren Ursprung — der Abruf erfolgt Browser → Remote-Bild, und das Ergebnis wird clientseitig gerendert. Ein Angreifer, der eine Remote-Bild-URL kontrolliert, kann nachverfolgen, dass die URL geladen wurde (eine Log-Zeile auf seinem eigenen Server), kann aber nichts von unserer Seite exfiltrieren.
Subresource Integrity (SRI)
Alles JavaScript und CSS, das wir ausliefern, ist same-origin. Wir laden keine Skripte oder Stylesheets von Drittanbietern, daher sind SRI-Hashes nicht anwendbar. Wenn wir jemals ein Drittanbieter-Asset laden, werden wir ein SRI-integrity-Attribut daran anbringen und den Hash-Aktualisierungsprozess auf dieser Seite dokumentieren.
Eine Schwachstelle melden
Wenn Sie ein Sicherheitsproblem entdecken, das Abundera QR betrifft — sei es in unserem Code, unserer Bereitstellung oder einer Abhängigkeit, die wir ausliefern — melden Sie es bitte vertraulich an security@abundera.ai. Wir streben eine Triage innerhalb von 72 Stunden an. Sie können uns auch über die Kontaktdaten in unserer /.well-known/security.txt-Datei erreichen.
Kein Bug-Bounty-Programm (noch nicht)
Wir bieten derzeit keine bezahlten Prämien an, aber jeder bestätigte gültige Bericht erhält eine Erwähnung im Changelog und unseren öffentlichen Dank.
Überprüfen Sie das oben Genannte
Jede Behauptung auf dieser Seite ist über die DevTools Ihres Browsers falsifizierbar, ohne uns vertrauen zu müssen:
- CSP: DevTools → Netzwerk →
/→ Header. Lesen Sie denContent-Security-Policy-Antwort-Header. - HSTS + Sicherheits-Header: gleicher Ort — alle
Strict-Transport-Security,X-Frame-Optionsusw. sind sichtbar. - Keine ausgehenden Aufrufe: DevTools → Netzwerk → Fetch/XHR. Generieren Sie einen QR-Code. Beobachten Sie, wie die Anzahl bei null bleibt.
- Service-Worker-Scope: DevTools → Anwendung → Service Workers. Überprüfen Sie die Skriptquelle und die Liste der gecachten Assets.
- Keine Cookies: DevTools → Anwendung → Cookies. Leer.
- Vollständige Anleitung: der Verifizierungsabschnitt des Manifests.
Kontakt
Sicherheitsmeldungen: security@abundera.ai