„Bolt-Sicherheit" sind zwei Dinge, die man auseinanderhalten sollte. Das erste ist das Bolt-Projekt selbst: was du in den Chat einfügst, wo Umgebungsvariablen landen, mit wem du das Projekt teilst und wohin es deployed wird. Das zweite ist der Code, den Bolt erzeugt, fast immer eine Vite-React-SPA mit Supabase, die dieselben fünf oder sechs Fehler wie immer mitbringt. Dieser Guide deckt beides ab, mit einer Anweisungsdatei, damit Bolt die Regeln bei jeder Generierung anwendet, einem Review-Prompt vor dem Deploy und der Methode, das Ergebnis von außen zu prüfen.
Teil 1: Dein Bolt-Projekt absichern
Bolt läuft in deinem Browser, und das ändert, wo Schlüssel leben
Bolt führt das ganze Projekt mit WebContainers im Browser aus. Während du entwickelst, gibt es keinen eigenen Server, also steckt jeder Schlüssel aus einer .env-Datei im Projekt, und mit dem Präfix VITE_ landet er eingebettet im Bundle, das deployed wird. Für den Browser ist das nur bei öffentlichen Schlüsseln in Ordnung (Supabases anon, Stripes publishable). Geheime haben im Frontend nichts verloren: Sie gehören in eine Supabase Edge Function oder eine Netlify-Funktion, und der Client ruft die Funktion auf.
Was du in den Chat einfügst, landet im Code
Fügst du in der Unterhaltung einen Schlüssel ein, um einen Dienst „anzubinden", schreibt das Modell ihn dorthin, wo es ihn braucht, meist in eine Komponente. Von dort reist er zu jedem Besucher. Die Regel: Öffentliche Schlüssel kommen in die .env; geheime ins Dashboard des Dienstes, der die Funktion ausführt (Supabase oder Netlify), nie in den Chat. Und hast du einen versehentlich eingefügt, rotiere ihn: Der Verlauf behält ihn, auch wenn du ihn aus dem Code löschst.
Teilen, exportieren und deployen
Ein geteilter Projektlink zeigt den kompletten Code, inklusive .env. Prüf vor dem Teilen, was drin ist. Exportierst du nach GitHub, mach das Repository privat und behalte .env in der .gitignore. Das Ein-Klick-Deployment geht zu Netlify, auf eine .netlify.app-Subdomain oder deine eigene Domain; Netlify liefert TLS und die Weiterleitung auf HTTPS, aber keine Sicherheits-Header, und die Produktions-Umgebungsvariablen werden in dessen Dashboard konfiguriert, nicht in der .env des Projekts.
Supabase gehört dir
Die Supabase-Integration legt Tabellen, Policies und Funktionen aus dem Chat heraus an. RLS, Buckets und Auth-Einstellungen bleiben deine Verantwortung, und Bolt macht bei Policies dieselben Fehler wie Lovable. Der Sicherheits-Guide für Supabase enthält drei SQL-Abfragen, um das Projekt in einer Minute zu prüfen.
Teil 2: Die Fehler, die Bolt in deinen Code einbaut
- Geheime Schlüssel in Komponenten. Ein Aufruf an OpenAI oder Stripe aus React mit dem Schlüssel darin. Such nach
sk_,service_roleundBearerin deinem deployten Bundle. - Tabellen ohne RLS oder mit
using (true)-Policies. Scheitert eine Abfrage an Rechten, öffnet das Modell die Policy, statt sie zu reparieren. - Edge Functions ohne Authentifizierung. Das Template antwortet jedem mit
Access-Control-Allow-Origin: *; gibt die Funktion Geld aus, kann es jeder ausgeben. - Prüfungen nur in der Oberfläche. Die Admin-Seite wird versteckt, wenn du kein Admin bist, aber die API antwortet trotzdem.
- Source Maps in Produktion. Manche Vite-Templates bringen
build.sourcemap: truemit; das veröffentlicht deinen Originalcode neben dem minifizierten. - Unsichtbar für KI und Suchmaschinen. Das HTML kommt leer an, und die Bots von ChatGPT oder Perplexity sehen nichts. Zählt die Landingpage, prerendere sie oder trenn sie ab. Details in warum mit KI gebaute Apps für die KI unsichtbar sind.
- Keine Sicherheits-Header. Kein CSP, kein HSTS, kein X-Frame-Options. Bei Netlify kommen sie per Datei dazu.
Ein Block, den Bolt immer anwendet
Bolt liest die Datei .bolt/prompt deines Projekts als dauerhafte Anweisungen. Leg die Datei an und füg das ein:
Sicherheitsregeln dieses Projekts:
- Schreib nie geheime Schlüssel in Frontend-Code oder in VITE_-Variablen. Integrationen mit geheimen Schlüsseln kommen in eine Supabase Edge Function oder eine Netlify-Funktion, die den Schlüssel aus ihren Umgebungsvariablen liest.
- Jede neue Tabelle hat RLS aktiviert und eine explizite Policy pro Operation. Nutze using (true) oder with check (true) nur bei öffentlichem Nur-Lese-Inhalt und sag es mir, wenn du es tust.
- Jede Serverfunktion prüft das JWT des Nutzers, beschränkt Access-Control-Allow-Origin auf unsere Domain und validiert die Eingabe.
- Admin-Rechte werden in RLS oder auf dem Server geprüft, nie nur in der Oberfläche.
- Nutzerdateien kommen in private Buckets mit Policies und signierten URLs.
- build.sourcemap bleibt in Produktion deaktiviert.
- Setz einen echten Titel, eine echte Meta-Description und echte Open-Graph-Tags in die index.html.
Und die Header für Netlify, in einer Datei public/_headers, die mit der App deployed wird:
/*
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Ein Review-Prompt vor dem Deploy
Prüfe die Sicherheit dieses Projekts und ändere noch nichts. Antworte mit einer Liste:
1. Schlüssel oder Tokens im Frontend-Code oder in VITE_-Variablen, mit Datei und Zeile.
2. Tabellen ohne RLS und Policies mit using (true) oder with check (true).
3. Serverfunktionen, die das JWT nicht prüfen, mit Access-Control-Allow-Origin: * antworten oder die Eingabe nicht validieren.
4. Admin-Aktionen, die nur in der Oberfläche geschützt sind.
5. Öffentliche Buckets mit Nutzerdateien.
6. Aktiviertes build.sourcemap und fehlende _headers-Datei.
7. Metadaten in der index.html, die noch vom Template stammen.
Schlag für jeden Punkt die exakte Änderung vor und warte auf meine Bestätigung.
Prüf das Ergebnis von außen
curl -sI https://deinedomain.com | grep -iE "strict-transport|x-frame|x-content-type"
curl -s https://deinedomain.com | grep -oE '/assets/[^"]+\.js' | head -1
curl -s https://deinedomain.com/assets/index-XXXX.js | grep -oE "sk_live_[A-Za-z0-9]+|service_role|eyJhbGciOi[A-Za-z0-9_-]{20,}" | head -3
curl -sI https://deinedomain.com/assets/index-XXXX.js.map | head -1
Erwartet: Header vorhanden, kein Schlüssel im Chunk und ein 404 bei der Source Map. Danach teste die Supabase-API ohne Sitzung, wie es der Supabase-Guide erklärt. Scanaris führt diese Prüfungen und rund vierzig weitere in 30 Sekunden aus: Es erkennt, dass die App mit Bolt gebaut ist, sucht Geheimnisse im Bundle, prüft Source Maps, Header, CORS, Cookies und offengelegte Dateien, testet die Supabase-Tabellen ohne Sitzung und kontrolliert, ob dein Inhalt ohne JavaScript lesbar ist. Für jeden Fehler bekommst du einen Fix-Prompt zum Einfügen in den Bolt-Chat, und es kann täglich neu scannen, weil eine Neugenerierung einen behobenen Fehler zurückbringen kann.
Häufige Fragen
Sind VITE_-Variablen privat?
Nein. Vite bettet alles, was mit VITE_ beginnt, ins Bundle ein; so sagt es „das ist öffentlich". Geheime Schlüssel tragen dieses Präfix nicht und werden nicht aus dem Frontend gelesen.
Kann ich bei Netlify Sicherheits-Header setzen?
Ja, mit der Datei _headers im öffentlichen Ordner oder mit netlify.toml. Netlify wendet sie beim nächsten Deployment an; prüf es mit curl.
Was tue ich, wenn ich einen geheimen Schlüssel in den Bolt-Chat eingefügt habe?
Rotiere ihn beim Ursprungsdienst, auch wenn du ihn aus dem Code gelöscht hast: Der Projektverlauf und frühere Deployments behalten ihn. Füg ihn danach im Supabase- oder Netlify-Dashboard hinzu und bitte Bolt, die Integration in eine Funktion zu verschieben.