Regel-Katalog
Was der Vibe Code Rescue Scan prüft
Jede Prüfung des Rescue Scans hat einen stabilen, versionierten Code (z. B. RSC-SEC-014) und eine eigene Seite: was geprüft wird, warum es zählt und was zu tun ist. Der Katalog ist die offene Referenz hinter dem Score.
Eigene App kostenlos prüfenWie der Score entsteht
Der Score ist keine Meinung, sondern eine Rechnung. Hier steht sie vollständig — damit ihr jedes Ergebnis nachvollziehen und uns widersprechen könnt. Die Zahlen auf dieser Seite kommen direkt aus dem laufenden Code, nicht aus einer Doku, die veralten kann.
Gewichtung der Dimensionen
- Sicherheit
- 0.26
- Datenschutz (DSGVO)
- 0.20
- Skalierung & Kosten
- 0.14
- Barrierefreiheit (BFSG)
- 0.12
- Architektur & SEO
- 0.16
- Code-Qualität
- 0.12
Abzüge je Befund
Jede Dimension startet bei 100 Punkten. Jeder Befund zieht ab, je nach Schweregrad:
- Hoch
- −34
- Mittel
- −16
- Niedrig
- −7
- Hinweis
- −0
Abzüge aus „niedrig“-Befunden sind je Dimension bei 21 Punkten gedeckelt. Hygiene-Punkte sollen den Score drücken, aber nie allein das Urteil kippen — acht fehlende HTTP-Header sind kein kaputtes Fundament.
Vom Score zum Verdikt
- Ab 75 Punkten und ohne belegten Befund in Sicherheit oder Datenschutz: Go — die sichtbaren Signale wirken tragfähig. Schon ein einzelner Befund mittleren Schweregrads in diesen beiden Bereichen macht daraus „Iterate“, auch bei hohem Score: Grünes Licht neben einem Fund, den derselbe Report auflistet, wäre ein Widerspruch.
- 45 bis 74 Punkte: Iterate — lösbare Baustellen, in klarer Reihenfolge.
- Stopp gibt es ausschließlich bei mindestens einem Befund mit Schweregrad „hoch“ — also einem belegten Hochrisiko-Fund wie einer offenen Datenbank oder einem exponierten Generalschlüssel. Ein niedriger Score allein reicht dafür nicht.
Was nicht geprüft werden konnte, wird als „begrenzt prüfbar“ ausgewiesen und zählt nicht als perfekt. Ein Bereich ohne Befunde ist nur dann 100, wenn die nötige Prüfstufe wirklich gelaufen ist.
Methodik-Version 2026.09. Jede inhaltliche Regeländerung erhöht sie, damit ältere Ergebnisse einordenbar bleiben.
Sicherheit
Kein durchgängiges HTTPS
Prüft, ob die finale Antwort verschlüsselt ausgeliefert wird oder auf http endet.
HSTS-Header fehlt
Prüft, ob Strict-Transport-Security gesetzt ist und der erste Aufruf damit abgesichert wird.
Keine Content-Security-Policy
Prüft Header und Meta-Tag auf eine Content-Security-Policy als Schutzschicht gegen XSS.
MIME-Sniffing nicht unterbunden
Prüft, ob `X-Content-Type-Options: nosniff` das Erraten von Inhaltstypen verhindert.
Kein Clickjacking-Schutz
Prüft X-Frame-Options bzw. CSP `frame-ancestors` gegen das Einbetten in fremde Seiten.
CORS-Wildcard am öffentlichen Dokument
Erfasst `Access-Control-Allow-Origin: *` am HTML — allein keine Lücke, aber ein Prüf-Signal.
Server-Technologie preisgegeben
Erfasst Version-Header wie `X-Powered-By`, die gezielte Exploit-Suche erleichtern.
Cookies ohne Secure/HttpOnly
Prüft gesetzte Cookies auf die Flags Secure und HttpOnly.
Supabase-Client-Konfiguration sichtbar
Erfasst Projekt-URL und anon-Key im Bundle — erwartbar, aber Ausgangspunkt der Zugriffsprüfung.
Supabase service_role-Schlüssel im Client
Dekodiert JWTs im Bundle und meldet den Rollen-Claim `service_role`, der RLS vollständig umgeht.
Geheimschlüssel im ausgelieferten Code
Sucht Muster echter Geheimnisse (Stripe, AWS, GitHub, PEM) im HTML und in den Bundles.
Firebase-Backend erkannt
Erfasst Firebase-Konfiguration im Client — zulässig, entscheidend sind die Sicherheitsregeln.
.env-Datei öffentlich abrufbar
Ruft bekannte Env-Pfade ab und bestätigt Treffer inhaltlich anhand von KEY=VALUE-Zeilen.
.git-Verzeichnis öffentlich
Bestätigt ein ausgeliefertes `.git` über die Signaturen von `config` und `HEAD`.
Datenbank-Tabellen der anon-Rolle zugeteilt
Fragt mit dem von der App selbst veröffentlichten Client-Schlüssel den Schema-Endpunkt ab und listet die Tabellen, die der anon-Rolle zugeteilt sind — ohne einen Datensatz oder eine Zeilenzahl abzurufen. Zugeteilt heißt noch nicht lesbar: ob Zeilen herauskommen, entscheidet Row Level Security.
Datenbank-Tabellen anonym lesbar (nachgewiesen)
Beantwortet die eigentliche Frage: Kommen mit dem öffentlich ausgelieferten Schlüssel tatsächlich Zeilen heraus? Gezählt wird ausschließlich über den `Content-Range`-Header einer HEAD-Anfrage — es wird keine einzige Zeile abgerufen.
Google API-Schlüssel im Client
Erfasst Schlüssel im Format `AIza…` im ausgelieferten Code — bei Maps und Firebase vorgesehen, riskant ohne Domain-Beschränkung.
Datenbank-Zugangsdaten im Client sichtbar
Findet Connection-Strings mit eingebettetem Benutzer und Passwort im HTML oder in den Bundles.
Firestore-Collections anonym lesbar
Fragt die Collections, die die App selbst im Bundle nennt, mit dem öffentlichen Web-Schlüssel an — mit `mask.fieldPaths=__name__`, also nur Dokument-Namen, kein einziger Feldwert.
Datenbank-Funktionen für anonyme Aufrufer freigegeben
Listet die der anon-Rolle zugeteilten RPC-Funktionen aus der Schema-Beschreibung — gelesen, nicht aufgerufen.
Registrierung offen, Konten sofort bestätigt
Liest die anonym abrufbare Auth-Konfiguration: Selbstregistrierung offen und E-Mail-Bestätigung deaktiviert.
KI-API direkt aus dem Browser gerufen (statisch belegt)
Findet Endpunkte von KI-Anbietern im ausgelieferten Code. Mit passendem Schlüssel-Muster im selben Bundle `high`, ohne `medium`.
Browser schreibt direkt in die Datenbank
Findet Schreibaufrufe (`insert`, `update`, `upsert`, `delete`, Storage-Upload) im ausgelieferten Code bzw. in `use client`-Dateien.
Zugangsdaten fest im Browser-Code verglichen
Findet Vergleiche wie `password === "…"` gegen ein festes Literal im ausgelieferten Code.
Storage-Buckets öffentlich listbar
Prüft, ob Datei-Buckets ihre Objektliste anonym herausgeben.
Firebase-Datenbank anonym lesbar
Fragt den Realtime-Database-Endpunkt mit `shallow=true` ab: antwortet er mit Schlüsselnamen statt „permission denied“, ist die Datenbank offen.
Geschützter Bereich nur im Browser abgesichert
Erkennt Admin-/Konto-Routen, die der Client-Router kennt, deren Schutz aber ausschließlich als Bedingung im Bundle steht — wer die URL kennt, ist drin.
Rollenprüfung im Client-Bundle
Findet Rollenvergleiche wie `role === "admin"` im ausgelieferten JavaScript — im Browser beliebig manipulierbar.
Zugangstoken in localStorage
Beobachtet zur Laufzeit, ob ein JWT-artiger Wert in Web-Storage landet — per XSS auslesbar.
KI-API direkt aus dem Browser gerufen
Beobachtet Aufrufe an LLM-Anbieter aus dem Client — der dafür nötige Schlüssel liegt damit offen und jeder Besucher kann auf eure Rechnung generieren.
Backup- oder Datenbank-Dump öffentlich
Prüft typische Dump-/Backup-Pfade und bestätigt Treffer über SQL- bzw. Archiv-Signaturen.
Keine Permissions-Policy
Prüft, ob Kamera, Mikrofon und Standort per Header explizit eingeschränkt werden.
Keine Referrer-Policy
Prüft, ob ausgehende Links interne URLs samt Query an Dritte weitergeben.
Unverschlüsselte Inhalte auf HTTPS-Seite
Findet per `http://` eingebundene Skripte, Stylesheets oder Bilder auf einer https-Seite.
Anmeldung ohne erkennbare Sperre
Sendet nach Ownership-Nachweis eine kleine Serie fehlerhafter Anmeldeversuche und prüft, ob überhaupt gebremst wird.
Admin-Bereich anonym erreichbar
Ruft entdeckte Verwaltungs-Pfade anonym auf und meldet, wenn Inhalt statt Weiterleitung zur Anmeldung kommt.
Tabellen ohne Row Level Security
Sammelt alle `create table` und alle `enable row level security` über sämtliche Migrationen und meldet Tabellen, die nie geschützt werden.
RLS-Policy erlaubt allen Zugriff
Findet Policies mit `using (true)` — RLS ist aktiv, wirkt aber nicht.
RLS-Policy prüft nur die Anmeldung, nicht den Eigentümer
Findet Policies mit `auth.role() = 'authenticated'` oder `auth.uid() is not null` ohne Bezug auf den Datensatz-Eigentümer.
RLS-Policy erlaubt beliebiges Schreiben
Findet `with check (true)` — die Lesebedingung kann streng sein, geschrieben werden darf trotzdem alles.
Edge Function ohne JWT-Prüfung
Findet `verify_jwt = false` in `supabase/config.toml` — die Serverfunktion ist ohne Anmeldung aufrufbar.
Firebase-Regeln erlauben allen Zugriff
Findet `allow …: if true` in `.rules`-Dateien — Firestore oder Storage stehen offen.
service_role-Schlüssel im Quellcode
Dekodiert JWTs in Quelldateien und meldet den Rollen-Claim `service_role`.
Geheimschlüssel im Quellcode
Sucht Muster echter Geheimnisse in Quelldateien (Stripe, AWS, OpenAI, Anthropic, Slack, SendGrid, PEM).
Datenbank-Zugangsdaten im Klartext
Findet Connection-Strings mit eingebettetem Benutzer und Passwort.
.env-Datei versioniert
Erkennt eine `.env` mit gesetzten Werten im Quellstand (nicht `.env.example`).
Supabase genutzt, Schema nicht versioniert
Meldet, wenn Supabase im Code steckt, aber keine Migrationen mit Tabellen und RLS vorliegen — dann ist der Zugriffsschutz aus dem Code nicht verifizierbar.
Geheimnis über öffentliches Env-Präfix exponiert
Findet Variablen mit öffentlichem Bundler-Präfix (`NEXT_PUBLIC_`, `VITE_`, `REACT_APP_`, `PUBLIC_`, `EXPO_PUBLIC_` …), deren Name auf ein Geheimnis hindeutet — solche Werte landen fest im Client-Bundle.
Env-Datei im ausgelieferten Bundle
Erkennt eine `.env` mit gesetzten Werten unter den aus Source Maps rekonstruierten Dateien — der Build hat sie mit ausgeliefert.
Server Action ohne Zugriffsprüfung
Wertet den Körper jeder `"use server"`-Funktion aus, die schreibend auf die Datenbank zugreift, und meldet fehlende Identitätsprüfung — Server Actions sind öffentliche Endpunkte.
Abhängigkeiten mit bekannter Schwachstelle
Gleicht die Paketversionen des Repos gegen die öffentliche OSV-Datenbank ab und nennt die betroffenen Pakete mit Advisory-ID.
Geheimschlüssel in der Git-Historie
Prüft die hinzugefügten Zeilen der letzten Commits gegen dieselbe Musterliste wie den aktuellen Stand — ein gelöschter Schlüssel bleibt lesbar.
Env-Datei war im Repository und wurde entfernt
Meldet Umgebungsdateien, die in der geprüften Historie auftauchen, im aktuellen Stand aber fehlen — die alten Werte bleiben abrufbar.
Angemeldete Fremde lesen fremde Datensätze
Legt nach Domain-Nachweis ein Wegwerf-Konto an und zählt, wie viele Zeilen dieses fremde Konto in personenbezogenen Tabellen sieht — ohne eine einzige Zeile abzurufen.
Tabelle für jeden Angemeldeten vollständig lesbar
Meldet Tabellen, die anonym verborgen sind, einem frisch angelegten Fremdkonto aber alle Zeilen zeigen — bei Katalogdaten gewollt, sonst derselbe Fehler wie bei personenbezogenen Tabellen.
Mandantentrennung hält im Test
Bestätigt, dass ein frisch angelegtes Konto ohne eigene Daten in den geprüften Tabellen keine Zeilen sah.
Prüfung auf fremde Datensätze nicht durchführbar
Hält fest, dass kein Konto angelegt werden konnte (Registrierung zu oder Bestätigung nötig) — die Mandantentrennung bleibt damit ungeprüft.
Zugriffsprüfung erst nach dem Schreibzugriff
Vergleicht die Position von Auth-Aufruf und Datenbank-Schreibvorgang im selben Funktionskörper und meldet, wenn geprüft wird, nachdem geschrieben wurde.
Auth-Ergebnis wird nie ausgewertet
Meldet Funktionen, die die Identität abfragen, das Ergebnis aber weder prüfen noch an den Schreibvorgang binden — der Aufruf bleibt wirkungslos.
API-Route ohne Zugriffsprüfung
Findet Route Handler mit schreibenden Methoden, in denen keine Authentifizierung vorkommt.
Eingaben ungeprüft in die Datenbank
Verfolgt Request-Bodies, die ohne Schema-Validierung in ein Insert oder Update fließen (Mass Assignment).
Webhook ohne Signaturprüfung
Erkennt Zahlungs-Webhooks, die den Payload verarbeiten, ohne die Signatur zu verifizieren — jeder kann dann Zahlungen vortäuschen.
Ungeprüftes HTML gerendert
Findet `dangerouslySetInnerHTML` mit dynamischem Wert — der klassische XSS-Pfad.
Datenschutz (DSGVO)
Google Fonts zur Laufzeit geladen
Findet Einbindungen von fonts.googleapis.com/gstatic.com, bei denen die IP der Nutzer an Google geht.
US-Tracking ohne sichtbare Einwilligung
Erkennt Analytics- und Pixel-Skripte mit Drittland-Transfer im ausgelieferten Markup.
Pflichtangaben nicht sichtbar
Prüft bei deutschsprachigen Zielen, ob Impressum und Datenschutzerklärung verlinkt sind.
Datenschutz-Signale unauffällig
Standardisierte Einordnung, wenn von außen keine Drittland-Transfers erkennbar sind.
Tracker feuern vor der Einwilligung
Beobachtet im Browser, welche Third-Party-Hosts schon beim ersten Aufruf kontaktiert werden, bevor irgendetwas zugestimmt wurde — der belegbare Verstoß, den statische Prüfungen nur vermuten können.
Daten an Drittland-Dienste
Listet zur Laufzeit kontaktierte Fremd-Hosts, die typischerweise außerhalb der EU verarbeiten.
Tracker ohne Consent-Oberfläche
Meldet einwilligungspflichtige Skripte, ohne dass im Markup irgendeine Consent-Mechanik erkennbar ist.
Tracking-Cookies ohne Einwilligung gesetzt
Beobachtet im Browser, welche Cookies gesetzt werden, bevor irgendeine Einwilligung erteilt wurde.
Fremd-Cookies ohne Einwilligung gesetzt
Meldet Cookies fremder Domains, die vor jeder Einwilligung gesetzt wurden.
Einwilligung ohne gleichwertiges Ablehnen
Prüft im gerenderten Zustand, ob neben dem Zustimmen auch ein Ablehnen auf derselben Ebene steht.
Skalierung & Kosten
Abfragen ohne Limit
Findet Datenbank-Abfragen, die ganze Tabellen ohne `limit`/`range` laden — funktioniert bei 10 Datensätzen, kippt bei 10.000.
Sehr großes JavaScript-Bundle
Misst die ausgelieferten Skript-Bytes gegen ein Budget — jedes Megabyte kostet Ladezeit und mobile Abbrüche.
Bilder ohne Optimierung
Zählt Bilder ohne Größenangabe oder moderne Formate — treibt Traffic-Kosten und Layout-Sprünge.
Keine Cache-Strategie
Prüft, ob Antworten Cache-Direktiven tragen — ohne sie zahlt jeder Aufruf den vollen Preis.
Antworten unkomprimiert
Prüft, ob Text-Antworten mit gzip/brotli ausgeliefert werden.
Abfragen in der Schleife (N+1)
Erkennt `await` innerhalb einer Schleife über Datensätze — pro Zeile ein Roundtrip.
Schwerer erster Seitenaufruf
Misst im Browser die tatsächlich übertragenen Bytes des ersten Aufrufs.
Skalierungs-Signale unauffällig
Standardisierte Einordnung, wenn Bundle, Caching und Bilder im Rahmen liegen.
Barrierefreiheit (BFSG)
Keine Sprachauszeichnung
Prüft das `lang`-Attribut am `<html>`-Element — ohne es liest der Screenreader in der falschen Sprache vor.
Bilder ohne Alternativtext
Zählt `<img>`-Elemente ohne `alt`-Attribut im ausgelieferten Markup.
Formularfelder ohne Label
Findet Eingabefelder ohne zugeordnetes Label oder `aria-label` — mit Screenreader nicht bedienbar.
Barrierefreiheits-Verstöße im gerenderten Zustand
Führt axe-core gegen die fertig gerenderte Seite aus und meldet die Verstöße nach Schweregrad — die Prüfung, die statische Analyse nicht leisten kann.
BFSG-Relevanz erkannt
Erfasst Hinweise auf Verkauf oder Dienstleistung an Verbraucher — dann greift das Barrierefreiheitsstärkungsgesetz für den digitalen Auftritt.
Barrierefreiheits-Signale unauffällig
Standardisierte Einordnung, wenn Sprache, Alternativtexte und Labels im Markup vorhanden sind.
Architektur & SEO
Plattform erkannt
Erkennt die verwendete No-Code-/KI-Plattform und gewichtet deren typische Lücken.
Framework-Stack erkannt
Erkennt den Framework-Stack bei framework-nativen Builds (Cursor, Claude Code, klassisch).
Domain-Inhaberschaft nachgewiesen
Bestätigt einen erbrachten Nachweis (DNS-TXT oder Datei) und schaltet die aktiven Prüfungen frei.
Wegwerf-Konto für die Prüfung angelegt
Benennt das Konto, das der Scan für den Nachweis der Mandantentrennung über eure Selbstregistrierung angelegt hat — damit es löschbar bleibt.
Inhalt nur clientseitig gerendert
Erkennt leere Root-Container mit kaum Text im initialen HTML.
Grundlegende Metadaten fehlen
Prüft Seitentitel und Meta-Description im Dokument.
Unveränderter Vorlagen-Titel
Erkennt Generator-Standardtitel wie „Vite + React“ — Hinweis auf ungeprüfte Tool-Defaults.
Kein Canonical-Link
Prüft, ob die Seite eine kanonische URL benennt (Duplicate-Content-Schutz).
Nicht existierende Pfade antworten mit 200
Ruft einen zufälligen Pfad ab: liefert die App dort Inhalt mit Status 200, kann weder Browser noch Suchmaschine Fehler erkennen.
Keine robots.txt und keine Sitemap
Prüft, ob das Ziel Crawling-Hinweise und eine Sitemap ausliefert.
Sehr großes Dokument — Auswertung teilweise
Hält fest, dass das HTML-Dokument die Prüfgrenze überschritten hat und nur bis dorthin ausgewertet wurde. Kein Mangel, sondern eine Angabe zur Abdeckung.
Code-Qualität
Source Maps öffentlich
Erkennt ausgelieferte Source Maps, aus denen sich der Originalquellcode rekonstruieren lässt.
Debug-Reste im Auslieferungsstand
Findet `console.log`, `debugger` oder TODO-Marker im Produktions-Bundle.
Code-Interna begrenzt sichtbar
Transparenz-Finding: ohne Source Maps oder Repo-Zugang lässt sich Code-Qualität nicht seriös bewerten.
Nicht alle Bundles ausgewertet
Hält fest, dass die Bundle-Auswertung an der Budgetgrenze endete — Funde bleiben gültig, das Fehlen von Funden sagt nichts.
Quellcode aus Source Maps rekonstruiert
Transparenz-Finding: benennt, wie viele Originaldateien aus öffentlichen Source Maps gelesen wurden.
Abdeckung des Deep-Scans
Transparenz-Finding: benennt die Anzahl read-only analysierter Repository-Dateien.
Keine Dateien lesbar
Meldet einen Deep-Scan ohne gelesene Quelldateien — das Ergebnis ist dann nicht aussagekräftig.
Repository nur teilweise gelesen
Meldet, dass die Dateiauswahl an der Budgetgrenze abgeschnitten wurde — Abwesenheits-Regeln schweigen dann, und ein GO ist ausgeschlossen.