Als je een app met Claude of Cursor hebt gecodeerd en je staat op het punt deze aan een betalende klant over te dragen, stop. AI-gegenereerde code bevat voorspelbare beveiligingsgaten — blootgestelde API-sleutels, ontbrekende invoervalidatie, standaarddatabasemachtigingen waarmee elke gebruiker de gegevens van iedereen kan zien. Dit zijn geen randgevallen. Ze komen voor in bijna elke eerste versie van AI-gegenereerde codebases.
Deze gids is de veiligheid checklist voor de lancering. Volg deze stap voor stap voordat echte gebruikers je app gebruiken. Het is geschreven voor de meest voorkomende vibe coding stack (Next.js + Supabase + Vercel), maar de principes gelden ongeacht welke tools je gebruikt.
Waarom AI-gegenereerde code beveiligingsproblemen heeft
AI-modellen optimaliseren voor "werkt het?" niet "is het veilig?" Wanneer je Claude vertelt "bouw me een taakbeheerder met gebruikersaccounts", genereert het code die gebruikers maakt, taken opslaat en weergeeft. Wat het waarschijnlijk niet automatisch doet: ervoor zorgen dat gebruiker A de taken van gebruiker B niet kan zien, valideren dat invoervelden geen schadelijke scripts kunnen accepteren, je API-sleutels verbergen voor de browserconsole, of snelheidslimieten toevoegen om te voorkomen dat iemand je endpoints bombardeert.
Dit zijn geen fouten van de AI — dit zijn hiaten in je prompt. De AI bouwt wat je hebt gevraagd. Je hebt waarschijnlijk niet om beveiliging gevraagd omdat je gericht was op functies. Nu is het tijd om terug te gaan en het toe te voegen.
Stap 1: Controleer je omgevingsvariabelen
Dit is de meest voorkomende en gevaarlijkste fout in vibe-coded apps. Zoek in elk bestand van je project naar hardcoded API-sleutels, database-URL's of geheimen.
Waar moet je naar zoeken: Doorzoek je codebase op strings die beginnen met sk-, eyJ, sbp_, supabase, postgres://, of lange willekeurig ogende strings. Controleer deze bestanden specifiek: elk bestand in je /app of /pages directory, elk componentbestand, je next.config.js, en alle hulpprogramma's.
De oplossing: Verplaats elk geheim naar omgevingsvariabelen. In Next.js worden alleen variabelen met het voorvoegsel NEXT_PUBLIC_ blootgesteld aan de browser. Je database-URL, service role sleutel en API-geheimen mogen dit voorvoegsel nooit hebben.
# .env.local (NOOIT naar Git committen)
SUPABASE_SERVICE_ROLE_KEY=your-secret-key
DATABASE_URL=postgres://...
# Deze zijn oké om bloot te stellen aan de browser:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
Controleer: Controleer dat je .gitignore bestand .env.local bevat. Als je al geheimen hebt gecommit naar Git, staan ze in je geschiedenis — zelfs na verwijdering — roteer (hergeneer) onmiddellijk elke blootgestelde sleutel.
Stap 2: Schakel Row-Level Security in Supabase in
Dit is de kritiekste stap als je Supabase gebruikt. Standaard hebben Supabase-tabellen geen toegangsbeperkingen — iedereen met je anon-sleutel kan elke rij in elke tabel lezen en schrijven. Dit betekent dat gebruiker A de gegevens van gebruiker B kan zien met een eenvoudige API-aanroep.
De oplossing: Schakel Row-Level Security (RLS) in op elke tabel en maak vervolgens beleid aan dat toegang beperkt.
Ga naar je Supabase dashboard → Table Editor → selecteer elke tabel → klik "RLS Disabled" om het in te schakelen. Voeg vervolgens beleid toe:
Voor een typische app waarin gebruikers alleen hun eigen gegevens moeten zien, maak een SELECT-beleid aan: auth.uid() = user_id. Maak vergelijkbare beleidsregels voor INSERT, UPDATE en DELETE.
Test het: Log in als gebruiker A en probeer de gegevens van gebruiker B via de API te openen. Als je deze kunt zien, is je beleid onjuist. Supabase heeft een SQL-editor waar je beleid rechtstreeks kunt testen.
Veel voorkomende AI-fout: Claude genereert vaak Supabase-queries met behulp van de service_role sleutel (die RLS omzeilt) in plaats van de anon sleutel met correct RLS-beleid. Controleer dat je client-side code alleen de anon-sleutel gebruikt. De service role sleutel mag alleen in server-side code bestaan (API-routes, server-acties) en nooit blootgesteld worden aan de browser.
Stap 3: Voeg authenticatie correct toe
AI-gegenereerde auth-code werkt vaak maar maakt shortcuts. Controleer deze specifieke problemen:
Sessiebeheer: Zorg ervoor dat sessies verlopen. Controleer dat je auth-setup een redelijke sessietime-out bevat (Supabase-standaarden zijn over het algemeen goed, maar controleer dit). Zorg ervoor dat afmelden de sessie daadwerkelijk ongeldig maakt en niet alleen de lokale cookie wist.
Wachtwoordvereisten: Als je email/wachtwoord-authenticatie hebt, erzwing minimale wachtwoordlengte (8+ tekens). Supabase verwerkt dit in je projectinstellingen → Authenticatie → Wachtwoordvereisten.
Beveiligde routes: Elke pagina die gebruikersspecifieke gegevens weergeeft, heeft authenticatie middleware nodig. In Next.js App Router maak je een middleware die controleert op een geldige sessie en ongeauthenticeerde gebruikers naar de inlogpagina stuurt. Vertrouw niet alleen op client-side controles — een gebruiker kan deze omzeilen door rechtstreeks je API aan te roepen.
E-mailverificatie: Schakel e-mailbevestiging in in Supabase Auth-instellingen. Dit voorkomt dat mensen accounts maken met valse e-mailadressen en voegt een basislaag accountgeldigheid toe.
Krijg je hier waarde uit? We publiceren één deep-dive per week over AI-tools, workflows en praktische gidsen. Word lid van lezers die het eerst lezen →
Stap 4: Valideer alle invoer
AI-gegenereerde formulieren hebben meestal basisvalidatie (vereiste velden, e-mailindeling) maar beschermen zelden tegen schadelijke invoer.
Wat moet je toevoegen:
Server-side validatie op elk API-eindpunt. Vertrouw nooit alleen op client-side validatie — deze kan worden omzeild door aanvragen rechtstreeks naar je API te verzenden. Gebruik een validatiebibliotheek zoals Zod (voor TypeScript) om schema's te definiëren voor elk gegevensstuk dat je app accepteert.
Maak HTML onschadelijk in gebruiker-gegenereerde inhoud die in de browser wordt weergegeven. Als je app opmerkingen, beschrijvingen of een tekstbestand heeft dat in de browser wordt weergegeven, gebruik een bibliotheek zoals DOMPurify om schadelijke scripts te verwijderen. Zonder dit kan iemand JavaScript injecteren die sessies van andere gebruikers steelt (cross-site scripting / XSS).
Beperk bestandsupload grootte en typen als je app bestandsuploads accepteert. AI-gegenereerde upload-handlers hebben vaak geen limieten, wat betekent dat iemand een bestand van 2GB of een uitvoerbaar bestand kan uploaden. Voeg groottelimieten toe (5MB is redelijk voor de meeste apps) en beperk bestandstypen tot wat je werkelijk nodig hebt (afbeeldingen, PDF's, enz.).
Stap 5: Beveilig je API-routes
Controleer elke API-route of server-actie in je app op deze problemen:
Authenticatie op elk eindpunt. Elke API-route die gebruikersgegevens retourneert of wijzigt, moet eerst de sessie van de gebruiker verifiëren. AI genereert vaak API-routes die aanvragen van iedereen accepteren.
Autorisatie naast authenticatie. Zelfs nadat je hebt bevestigd dat een gebruiker is ingelogd, controleer of ze het specifieke resource waartoe ze toegang aanvragen mogen raadplegen. "Gebruiker A is ingelogd" betekent niet "gebruiker A kan het profiel van gebruiker B bewerken." Controleer eigendom bij elke gegevenstoegang.
Snelheidslimieten. Zonder snelheidslimieten kan iemand duizenden aanvragen per seconde naar je API sturen, om gegevens te schrapen of je server te overweldigen. Voeg basissnelheidslimieten toe met behulp van een bibliotheek zoals rate-limiter-flexible of gebruik Vercel's ingebouwde snelheidslimieten op Edge Functions.
HTTP-methodes. Zorg ervoor dat je API-routes alleen reageren op de HTTP-methodes waarvoor ze zijn bestemd. Een route die POST-aanvragen verwerkt, mag niet ook op DELETE-aanvragen reageren tenzij je dit expliciet hebt ontworpen.
Stap 6: Controleer je deployment-configuratie
Je deployment-platform heeft beveiligingsinstellingen die AI niet voor je configureert.
Vercel-instellingen om te controleren: Schakel "Deployment Protection" in (vereist auth om preview-deployments te bekijken — voorkomt dat klanten preview-URL's per ongeluk delen waarmee onafgewerkt werk wordt blootgesteld). Stel uitgavenlimits in om onverwachte kosten te voorkomen als je app verkeerspieken ontvangt. Configureer je toegestane domeinen in CORS-headers.
Aangepast domein en SSL: Als je dit aan een klant levert, stel hun aangepaste domein in met HTTPS. Vercel en Netlify verwerken SSL automatisch. Lever nooit een klanten-app op een .vercel.app subdomein — het ziet er niet professioneel uit en de klant kan het niet eenvoudig overdragen.
Headers: Voeg beveiligingsheaders toe aan je next.config.js of vercel.json: X-Content-Type-Options: nosniff, X-Frame-Options: DENY (voorkomt dat je site in iframes wordt ingebed voor clickjacking), Strict-Transport-Security (dwingt HTTPS af). Dit zijn eenmalige toevoegingen die hele klassen aanvallen voorkomen.
Stap 7: Voer een laatste beveiligingsscan uit
Voordat je iets aan een klant levert, voer deze gratis controles uit:
npm audit: Voer npm audit uit in je projectmap. Het markeert bekende kwetsbaarheden in je afhankelijkheden. Repareer kritieke en ernstige problemen. Voer npm audit fix uit voor automatische reparaties waar beschikbaar.
Lighthouse: Open je gedeployde site in Chrome, open DevTools en voer een Lighthouse-audit uit. Controleer de score "Best Practices" — het vangt veel voorkomende beveiligingsproblemen op zoals ontbrekende HTTPS, kwetsbare biblioteken en onveilige headers.
Handmatig testen: Log in als een gebruiker en probeer de gegevens van een andere gebruiker te openen door URL's of API-aanroepen aan te passen. Probeer lege formulieren, oversized invoer en speciale tekens in te dienen (zoals gecodeerde XSS-payloads). Als een van deze werkt, heb je problemen om op te lossen.
De pre-launch checklist
Print dit en controleer elk item voordat je live gaat:
- Alle geheimen in omgevingsvariabelen (geen hardcoded sleutels)
.env.localin.gitignore(en geen geheimen in Git-geschiedenis)- Supabase RLS ingeschakeld op elke tabel
- RLS-beleidsregels getest (gebruiker A kan de gegevens van gebruiker B niet zien)
- Client-side code gebruikt alleen anon-sleutel (service role sleutel alleen server-side)
- Authenticatie op elk API-eindpunt
- Autorisatiecontroles (eigendomverificatie) bij gegevenstoegang
- Invoervalidatie op elk formulier (server-side, niet alleen client-side)
- Bestandsupload-limieten (grootte en type) indien van toepassing
- Snelheidslimieten op API-eindpunten
- Beveiligingsheaders geconfigureerd
npm audituitgevoerd en kritieke problemen opgelost- Aangepast domein met SSL geconfigureerd
- Preview-deployments beveiligd
- Test handmatige toegang tot gegevens van andere gebruikers geslaagd
De essentie
Een vibe-coded app beveiligen gaat niet over het worden van een beveiligingsexpert. Het gaat erover een checklist uit te voeren die de voorspelbare gaten vangt die AI achterlaat. De stappen hierboven kosten 2–4 uur en voorkomen de meest voorkomende kwetsbaarheden. Voor een klant-gerichte app is dit niet optioneel — dit is het verschil tussen professioneel werk en een aansprakelijkheid.
Als je je eerste vibe-coded app bouwt, begin met onze volledige gids voor vibe coding. Als je de prompts die je met Claude of Cursor gebruikt wilt verbeteren, probeer onze gratis prompt-optimizer. En voor een uitsplitsing van de beste coderingstools, zie Claude Code vs Codex.
Dit is wat we elke week doen. Één deep-dive over AI-tools, workflows en eerlijke meningen — geen hype, geen opvulling. Sluit je bij ons aan →
Disclosure: Some links in this article are affiliate links. We only recommend tools we've personally tested and use regularly. See our full disclosure policy.