Two customers can sign in successfully and still have access to each other's information. A login proves who someone is. Your app must separately decide what that person is allowed to read, change, download, or delete.
If you have built a customer portal with an AI coding tool, this distinction deserves attention before you trust it with real records. A page that looks private is not evidence that the underlying information is protected.
A hidden button is not a locked door
Consider a hypothetical invoice portal. Customer A sees only their own invoices in the list. However, the server returns any invoice when given its record identifier. The list is filtered correctly; the underlying access check is missing.
Removing an edit button or hiding an administrator menu does not solve that problem. The permission check has to apply where the information is returned or changed, even when a request arrives without going through the expected screen.
The same principle applies to file downloads, search results, exports, background jobs, and AI answers based on customer documents. Checking one page does not establish that all those paths respect the same boundary.
Write down the rules before testing them
Start with a small access table in plain language. An ordinary customer can see their company's invoices. A company administrator can invite teammates. A support operator may have a different, limited set of permissions. Someone removed from a company should lose its access.
Be explicit about what must be denied. “Customers can view invoices” is incomplete. “Customers can view invoices belonging to companies they currently belong to, and cannot access any others” gives an engineer a rule to implement and test.
If the app serves individual users rather than companies, use that ownership model. Do not add company-level complexity simply because a tutorial uses it.
Ask for evidence using invented customer accounts
Have a qualified engineer check a separate environment with two unrelated customer accounts and dummy records. The checks should cover reading, creating, changing, and deleting information, not only whether a dashboard loads.
- Can each account perform the actions it is meant to perform?
- Are cross-account requests rejected even when made directly to the server?
- Do files, search, and exports follow the same rules?
- Does removing a user's membership actually remove their access?
In Supabase, database permissions and row-level security policies both matter. Its official security guidance also explains that service-role access bypasses row-level security. A privileged key therefore cannot be treated like a safe browser credential. This is a reason to review the actual configuration, not paste a policy from another project and assume the problem is solved.
What if you already suspect an exposure?
Do not keep exploring real customers' records to see how far the problem goes. Preserve the evidence you already have, limit the affected access with professional help, and investigate which systems and records may be involved. Any communication or legal obligations need to be assessed against the facts of that incident.
A passing review gives evidence about the paths and configuration tested. It is not a permanent guarantee: new features can create new access paths, so the checks should run again as the product changes.
Five prompts to use with your AI coding assistant
Before you begin: Use the same project conversation for all five prompts. Inspect first, approve the plan yourself, and never test against live customer data or secrets.
These prompts assume your assistant can inspect the relevant project. Ask it to say clearly if it cannot. Use the prompts one at a time, reviewing each response before moving to the next step.
1. Map
Map my complete authentication and authorization design: sign-in, sessions, roles, organization membership, APIs, database queries, file access, exports, and background jobs. Reference source files and identify where every access decision is enforced.
2. Audit
Look for missing object-level authorization, frontend-only restrictions, overly broad data queries, unsafe file access, and inconsistent or redundant controls. Separate confirmed gaps from possibilities. Never access or reveal real customer data.
3. Plan
Propose a prioritized plan for consistent server-side and, where appropriate, database-level permission checks. Include synthetic multi-user tests, least-privilege rules, and an approach for existing data and migrations.
4. Challenge
Critique the design from an attacker-minded defensive perspective, including hidden endpoints, exports, links, jobs, and role changes. Design negative tests with fictional accounts and identify what requires independent security review.
5. Implement
After explicit approval and only in an isolated environment, implement the selected safeguards. Run positive and negative access tests with synthetic data. Report unresolved exposure paths; do not probe real users or deploy automatically.
If nobody can show you how customer boundaries are enforced, request an access-control review before expanding the app's use. DitchNow offers hands-on production hardening for founders in Amsterdam, Haarlem, and across the Netherlands. Discuss what your app stores and who should be able to access it.
About DitchNow
DitchNow is based in Haarlem, Netherlands, and helps founders and teams fix and extend software and put AI to work. Meet DitchNow.
