Door AI gegenereerde code werkt. Het draait. Het ziet er goed uit. Het wordt ook geleverd met dezelfde vijf beveiligingskwetsbaarheden in bijna elk project. Dit zijn geen theoretische risico's — het zijn de specifieke gaten die verschijnen in bijna elke codebase die door Claude, Cursor, Replit of Copilot wordt geproduceerd wanneer je niet expliciet om beveiliging vraagt.
Ik heb in het afgelopen jaar tientallen vibe-coded projecten gecontroleerd, en dezelfde vijf fouten verschijnen in minstens 80% ervan. Elk ervan kost minder dan 30 minuten om op te lossen. Hier is wat je moet zoeken en precies hoe je het kunt oplossen.
Fout 1: API-sleutels hardcoded in frontend-code
Hoe het gebeurt: Je vertelt Claude "verbind met Supabase" of "voeg Stripe-betalingen toe", en het genereert code met de API-sleutel rechtstreeks in een React-component. De code werkt perfect — en je geheime sleutel is zichtbaar voor iedereen die DevTools opent in de browser en het Network-tabblad of de JavaScript-bron controleert.
Waarom het gevaarlijk is: Je Supabase service role-sleutel omzeilt alle databasebeveiliging. Je Stripe-geheime sleutel laat iemand anders kaarten belasten of terugbetalingen doen. Je OpenAI-sleutel laat iemand duizenden in API-aanroepen op je account stapelen. Bots scannen actief openbare GitHub-repo's en geïmplementeerde sites naar blootgestelde sleutels.
De oplossing: Verplaats elke geheim naar omgevingsvariabelen. In Next.js bereiken alleen variabelen die beginnen met NEXT_PUBLIC_ de browser. Elke sleutel die schrijftoegang, beheerder-toegang of financiële toegang verleent, moet alleen server-side zijn.
Nadat je sleutels naar .env.local hebt verplaatst, zoek je je hele codebase naar de oude sleutelwaarden om er zeker van te zijn dat ze weg zijn. Controleer dan je Git-geschiedenis — als de sleutel ooit is committed, zit deze nog steeds in je repo-geschiedenis, zelfs als je deze hebt verwijderd. Genereer (roteer) elke sleutel die ooit is blootgesteld, ook al was het maar even.
Tijd om op te lossen: 15–30 minuten.
Fout 2: Supabase-tabellen zonder Row-Level Security
Hoe het gebeurt: AI genereert Supabase-tabelcreatie-queries en CRUD-operaties, maar schakelt Row-Level Security (RLS) niet in. Standaard zijn Supabase-tabellen met uitgeschakelde RLS volledig toegankelijk voor iedereen met je project-URL en anonieme sleutel — beide zijn openbaar (en moeten dat zijn).
Waarom het gevaarlijk is: Zonder RLS kan gebruiker A de gegevens van gebruiker B opvragen. Een eenvoudige fetch-aanroep vanuit de browserconsole kan elke rij uit elke tabel halen. Je hele database is effectief openbaar.
Hoe het op te sporen: Ga naar je Supabase-dashboard → Table Editor. Als een tabel "RLS Disabled" toont, heb je dit probleem. Controleer ook of je client-side code de service_role-sleutel gebruikt in plaats van de anon-sleutel — dat is nog erger.
De oplossing: Schakel RLS in op elke tabel. Maak vervolgens beleid aan dat aansluit bij de toegangspatronen van je app. Het meest voorkomende beleid: gebruikers kunnen alleen SELECT, INSERT, UPDATE en DELETE rijen uitvoeren waarbij auth.uid() = user_id. Test door je aan te melden als een gebruiker en te proberen de gegevens van een andere gebruiker via de Supabase REST API te benaderen.
Tijd om op te lossen: 30–60 minuten afhankelijk van het aantal tabellen.
Haal je er waarde uit? We publiceren elke week één diepgaande artikel over AI-tools, workflows en praktische beveiligingsgidsen. Sluit je aan bij de lezers die het eerst krijgen →
Fout 3: Geen invoervalidatie op formulieren of API-routes
Hoe het gebeurt: AI genereert formulieren die elke invoer accepteren en API-routes die erop vertrouwen dat alle binnenkomende gegevens correct zijn. Het formulier heeft een "required"-attribuut in HTML, maar geen server-side validatie. Iemand omzeilt het formulier geheel en al door een directe API-aanvraag met elke payload die ze willen te sturen.
Waarom het gevaarlijk is: Zonder server-side validatie kunnen aanvallers scripts in je database injecteren (opgeslagen XSS), oversized payloads sturen die je server laten vastlopen, of gegevens indienen die je app-logica breken (zoals een negatieve prijs of een e-mailveld met SQL).
Hoe het op te sporen: Open elke API-route of server-actie in je codebase. Als deze req.body of formuliergegevens gebruikt zonder de vorm, type en lengte van elk veld te controleren, heb je dit probleem.
De oplossing: Voeg server-side validatie toe aan elk eindpunt met behulp van een schema-validatie-bibliotheek. Zod is de standaard voor TypeScript-projecten:
import { z } from 'zod';
const taskSchema = z.object({
title: z.string().min(1).max(200),
description: z.string().max(2000).optional(),
priority: z.enum(['low', 'medium', 'high']),
});
// In your API route:
const parsed = taskSchema.safeParse(req.body);
if (!parsed.success) {
return Response.json({ error: parsed.error }, { status: 400 });
}
Voor elk veld dat als HTML wordt weergegeven (opmerkingen, beschrijvingen, bio's), saniteer ook de uitvoer met DOMPurify voordat je het weergeeft.
Tijd om op te lossen: 30–60 minuten.
Fout 4: Geen snelheidsbeperking op API-eindpunten
Hoe het gebeurt: AI voegt nooit snelheidsbeperking toe tenzij je erom vraagt. Elk API-eindpunt dat je app blootstelt kan duizenden keren per seconde door iedereen met een script worden bereikt.
Waarom het gevaarlijk is: Zonder snelheidsbeperking kan iemand je login-eindpunt brute-forcen, je database uitkammen door list-eindpunten herhaaldelijk te bereiken, je server overweldigen (denial of service), of je API-quota opgebruiken als je eindpunten externe services zoals OpenAI of Stripe aanroepen.
Hoe het op te sporen: Als geen van je API-routes controleert hoeveel aanvragen een enkel IP-adres of gebruiker onlangs heeft gedaan, heb je geen snelheidsbeperking.
De oplossing: De eenvoudigste aanpak voor apps die op Vercel worden gehost, is een in-memory snelheidsbeperking voor ontwikkeling en een Redis-gebaseerde voor productie. Vercel's Edge Middleware kan basissnelheidsbeperking verwerken. Upstash Redis (gratis laag) met @upstash/ratelimit geeft je productie-grade snelheidsbeperking in een kleine hoeveelheid code.
Een redelijk startpunt: 60 aanvragen per minuut voor geverifieerde gebruikers, 20 per minuut voor niet-geverifieerde gebruikers, en 5 per minuut voor login/signup-eindpunten (om brute-force te voorkomen).
Tijd om op te lossen: 20–45 minuten.
Fout 5: Ontbrekende authenticatiecontroles op beveiligde pagina's en API's
Hoe het gebeurt: AI genereert een prachtig dashboard en API-routes die gebruikersgegevens retourneren, maar voegt geen middleware toe om te verifiëren dat de gebruiker echt is ingelogd. De pagina "werkt" omdat je tijdens ontwikkeling altijd bent ingelogd. In productie kan iemand de dashboard-URL direct benaderen zonder in te loggen, of het API-eindpunt bereiken en gegevens terug krijgen.
Waarom het gevaarlijk is: Niet-geverifieerde toegang tot beveiligde pagina's betekent dat iedereen gebruikers-dashboards, beheerpanelen of privégegevens kan zien door simpelweg de URL te raden. Onbeveiligde API-routes betekenen dat elk gereedschap zoals Postman of curl gegevens kan ophalen zonder inloggegevens.
Hoe het op te sporen: Open een incognito-browservenster (niet ingelogd) en navigeer rechtstreeks naar je dashboard-, instellingen- of beheersURL's. Als je enige inhoud kunt zien zonder naar een inlogpagina te worden omgeleid, heb je dit probleem. Probeer dan je API-routes rechtstreeks te bereiken — als deze gegevens retourneren zonder een geldige sesscookie of auth-token, zijn die ook onbeveiligd.
De oplossing: Voeg authenticatie-middleware toe die voor elke beveiligde route wordt uitgevoerd. In Next.js App Router, maak je een middleware.ts in je projectroot:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const session = request.cookies.get('session');
if (!session) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/settings/:path*', '/api/protected/:path*'],
};
Pas de matcher aan om elke route die authenticatie vereist te dekken. Test in incognito nadat je deze hebt geïmplementeerd.
Tijd om op te lossen: 15–30 minuten.
Hoe je deze in toekomstige projecten voorkomt
Het patroon is duidelijk: AI genereert code die functioneel werkt maar beveiliging overslaat omdat je er niet om hebt gevraagd. De oplossing is er van het begin voor te vragen.
Voeg dit toe aan het einde van je initiële prompt voor elk vibe-coded project:
SECURITY REQUIREMENTS:
- All secrets in environment variables (never hardcoded)
- Supabase RLS enabled on all tables with per-user policies
- Server-side input validation on every API route (use Zod)
- Rate limiting on all public endpoints
- Authentication middleware on all protected routes
- No service role key in client-side code
Dit zal niet alles opvangen, maar het elimineert de vijf meest voorkomende kwetsbaarheden in de eerste doorgang in plaats van later opschoning te vereisen.
Als je beter wilt worden in het schrijven van prompts die van het begin af aan veiliger code opleveren, kan onze gratis prompt optimizer je helpen je instructies te structureren. En voor een volledige beveiligingsdoorloop, zie onze stap-voor-stap gids: Een vibe-coded app beveiligen voordat je deze aan klanten geeft.
Dit doen we elke week. Één diepgaand artikel over AI-tools, workflows en eerlijke meningen — geen hype, geen vulling. Sluit je bij ons aan →
Openbaarmaking: Sommige links in dit artikel zijn affiliate-links. We bevelen alleen tools aan die we persoonlijk hebben getest en regelmatig gebruiken. Zie ons volledige openbaarmakingsbeleid.