Waarom kunnen mijn gebruikers elkaars gegevens zien?
Het scherm laat de juiste dingen zien, dus het lijkt goed. Tot iemand een cijfer in de URL verandert. Wat Row Level Security is, waarom het uit staat, en hoe je het controleert zonder developer.
Dit is het probleem waar ik het vaakst voor word gebeld, en bijna altijd nadat het al een keer is misgegaan. Iemand belt dat hij de offerte van een ander bedrijf ziet. Of erger: iemand belt niet, en je komt er maanden later achter.
Wat er precies gebeurt
Je app haalt gegevens op uit een database. In de meeste vibecode-projecten is dat Supabase, en het ophalen gebeurt rechtstreeks vanuit de browser. Dat is een prima ontwerp, maar het betekent dat de database zelf moet bepalen wat iemand mag zien. De browser kan dat niet bepalen, want de browser staat op de computer van je gebruiker en die kan daar alles aan veranderen.
Het mechanisme dat dat regelt heet Row Level Security: regels op de tabel zelf, in de trant van 'je mag alleen rijen zien waar jouw gebruikersnummer in staat'. Staat dat aan en zijn de regels goed, dan krijgt een gebruiker die andermans gegevens opvraagt simpelweg niets terug. Staat het uit, dan krijgt hij alles.
Waarom het bij jou uit staat
Omdat het tijdens het bouwen in de weg zit. Supabase zet het standaard aan bij een nieuwe tabel, en het eerste dat er dan gebeurt is dat je scherm leeg blijft. De snelste oplossing is het uitzetten, of een regel toevoegen die iedereen alles toestaat. De app doet het weer, je bouwt verder, en niemand komt erop terug.
Dit is geen domheid en het is ook niet specifiek voor AI-tools. Het is gewoon wat er gebeurt als het ding dat je beschermt onzichtbaar is en het ding dat je bouwt zichtbaar.
Zelf controleren, in tien minuten
- Maak een tweede account aan met een ander e-mailadres, in je echte app.
- Log daarmee in en zoek een pagina met een nummer of code in het adres: /offerte/12, /project/abc.
- Verander dat nummer in iets dat bij je eerste account hoort en druk op enter.
- Zie je gegevens die van het andere account zijn, dan staat de afscherming alleen in het scherm.
Werkt dat niet omdat je geen nummers in je adressen hebt, kijk dan in Supabase zelf: onder Table Editor staat per tabel of RLS aan of uit staat. Elke tabel met klantgegevens waar het uit staat, is een tabel die iedereen met een sleutel uit je browser kan uitlezen.
Een scherm dat iets niet toont, verbergt niets. Het vraagt de gegevens op en besluit ze niet te tekenen. Ze zijn dan al verstuurd.
Wat de oplossing inhoudt
Per tabel bedenken wie welke rijen mag zien, aanmaken, wijzigen en verwijderen, en dat als regel vastleggen. Dat is denkwerk over je eigen proces, niet over techniek: hoort een medewerker de facturen van alle klanten te zien of alleen die van zijn eigen dossiers? Zodra die vragen beantwoord zijn, is het opschrijven ervan een kwestie van uren.
Wat er daarna hoort te komen is een test die het bewijst: een script dat als gebruiker A probeert bij de gegevens van B te komen en faalt als dat lukt. Zonder zo'n test weet je het bij de volgende wijziging weer niet zeker.
Als het al is misgegaan
Zet dan eerst de deur dicht en kijk daarna pas naar de rest. Ververs je sleutels, zet RLS aan op de tabellen met persoonsgegevens en accepteer dat een deel van je app tijdelijk leeg is. Een app die te weinig toont is te repareren; gelekte klantgegevens niet. En reken erop dat een echt datalek gemeld moet worden — dat is geen advies van mij, dat is de wet.