How I Would Fix database rules leaking customer data in a React Native and Expo AI-built SaaS app Using Launch Ready.
The symptom is usually ugly and expensive: one user logs in and can see another user's profile, invoices, messages, or uploaded files. In an AI-built...
How I Would Fix database rules leaking customer data in a React Native and Expo AI-built SaaS app Using Launch Ready
The symptom is usually ugly and expensive: one user logs in and can see another user's profile, invoices, messages, or uploaded files. In an AI-built React Native and Expo SaaS app, the most likely root cause is weak database authorization, not the mobile app itself.
The first thing I would inspect is the data access path end to end: auth claims, database rules or row-level security, API endpoints, and any client-side queries that are fetching too much data. If customer data is leaking, I assume the app is trusting the client too much until proven otherwise.
Triage in the First Hour
1. Check whether the leak is reproducible on a real device and in a fresh test account. 2. Confirm which data is exposed: profiles, orders, billing records, files, or admin-only records. 3. Review recent deploys from Expo, backend functions, and database rule changes. 4. Inspect auth logs for cross-account access patterns or missing user IDs. 5. Check the database rules or row-level security policies first. 6. Review any "temporary" admin bypasses, service keys, or debug flags in production. 7. Verify whether the app is using public client keys where secret keys should be server-only. 8. Look at network requests from the mobile app to see which table or endpoint returns too much data. 9. Check monitoring for spikes in 200 responses on sensitive endpoints with unusual response sizes. 10. Freeze risky releases until the access control path is understood.
A simple diagnostic pattern I use:
## Verify current deployment metadata and environment mismatch npx expo config --type public grep -R "service_role\|admin\|bypass\|debug" . -n ## Check whether sensitive queries are coming from the client ## Then compare with database policy definitions and server logs
If I can reproduce access across two accounts in under 15 minutes, I stop guessing and move straight into authorization review.
Root Causes
| Likely cause | What it looks like | How I confirm it | | --- | --- | --- | | Missing row-level security | Any authenticated user can read shared tables | Inspect table policies and test with two different user IDs | | Overbroad policy conditions | Users can read records where ownership checks are too loose | Compare policy predicates against actual `user_id` values | | Service key used in client code | App can read everything because it has admin privileges | Search Expo code and build artifacts for privileged keys | | Backend endpoint returns unfiltered data | Mobile app calls an API that ignores tenant boundaries | Trace request handlers and inspect query filters | | Auth claims not passed correctly | Database sees anonymous or wrong identity context | Decode token claims and verify session propagation | | Legacy debug access left on | A development shortcut still works in production | Search for feature flags, test routes, or temporary bypass logic |
In AI-built apps, I also expect one more failure mode: generated code that "works" but never got a security review. The model may have produced a query that fetches all rows first and filters on the device, which is a data leak waiting to happen.
The Fix Plan
My goal is to stop the leak without breaking onboarding or locking out legitimate users.
1. I would freeze writes to the affected area if needed.
- If billing or PII is exposed, I would temporarily disable risky reads while keeping core login working.
- This reduces blast radius while we patch access control.
2. I would move authorization enforcement to the server or database layer.
- Client-side filtering is not enough.
- Every sensitive table needs explicit ownership checks tied to authenticated identity.
3. I would tighten database rules or row-level security.
- Allow only `select`, `insert`, `update`, and `delete` actions that match the signed-in user or approved tenant scope.
- Deny by default.
4. I would remove any privileged secrets from the Expo client.
- Service-role keys must never ship inside a mobile bundle.
- Secrets belong in backend environments only.
5. I would patch any API route returning broad datasets.
- Add `user_id`, `org_id`, or tenant filters at query time.
- Paginate responses so one bad query cannot dump entire tables into memory.
6. I would rotate exposed credentials immediately.
- If a secret has been bundled into an app build, assume it is compromised.
- Rotate keys before redeploying.
7. I would add audit logging around sensitive reads.
- Log who accessed what, when, from where, and through which endpoint.
- Keep logs useful but not noisy enough to create another privacy problem.
8. I would redeploy only after validating with clean test accounts.
- One account should never be able to read another account's records after the fix.
For React Native and Expo specifically, my preference is to keep all privileged operations off-device unless there is a very strong reason not to. That trade-off slightly increases backend work, but it sharply reduces exposure risk and support load later.
Regression Tests Before Redeploy
I do not ship this kind of fix on hope alone. I want clear acceptance criteria and repeatable tests.
- Create two separate test users with different customer records.
- Confirm user A cannot read user B's private data through the app UI.
- Confirm user A cannot read user B's private data through direct API calls either.
- Test unauthenticated access to every sensitive endpoint or table path.
- Test expired tokens and revoked sessions.
- Verify admin-only records remain inaccessible to normal users.
- Confirm file URLs do not expose private assets without authorization checks.
- Validate that pagination still works under normal load with no missing rows for valid users.
- Run smoke tests on iOS and Android builds after redeploy.
Acceptance criteria I use:
- Zero cross-account reads in 20 repeated attempts across two accounts.
- No privileged secrets present in Expo public config or shipped bundle output.
- p95 read latency stays under 300 ms for normal authenticated requests after adding authorization checks.
- No increase in login failure rate above 1 percent after deployment.
- Support tickets about missing access stay below 2 during rollout verification.
I also want one manual exploratory pass on real devices because mobile apps often hide bad states behind cached screens or stale sessions.
Prevention
The best prevention is boring discipline around access control.
- Put authorization rules under code review every time they change.
- Require a second engineer to review any policy touching PII or billing tables.
- Add automated tests for tenant isolation and ownership checks before merge.
- Store secrets only in backend environment variables and secret managers.
- Use least privilege for every key, token, and service account.
- Add alerts for unusual bulk reads, repeated 403s, or sudden response size spikes.
- Review Expo release artifacts so no secret values are bundled into public builds.
I also recommend simple observability guardrails:
- Dashboard for auth failures by route
- Alert for cross-account access attempts
- Audit trail for admin actions
- Uptime monitoring on login, checkout, inbox, and profile endpoints
From a UX angle, do not hide authorization failures behind generic broken screens. Tell users clearly when content cannot be loaded due to permissions instead of leaving them stuck on spinners that increase support tickets.
When to Use Launch Ready
Launch Ready fits when you already know there is a serious production issue and you need fast containment plus safe deployment work around it.
It includes domain setup, email configuration, Cloudflare, SSL, caching, DDoS protection if needed at the edge layer you already control, SPF/DKIM/DMARC alignment, production deployment support, environment variables, secrets handling cleanup, uptime monitoring setup, redirects/subdomains if relevant to launch flow stability, and a handover checklist.
I would use it when:
- The app is live but unsafe
- You need domain or deployment cleanup before shipping a hotfix
- Secrets may have leaked into frontend builds
- Monitoring does not exist yet
- The founder needs a clean handoff after emergency remediation
What you should prepare before booking:
- Repo access
- Hosting provider access
- Database console access
- Current domain registrar access
- Email provider access
- List of known affected screens or endpoints
- Any recent error logs or screenshots showing the leak
My recommendation: do not try to patch this as a cosmetic bug fix inside another feature sprint. Treat it as production safety work first. If customer data leaked once because of weak rules today could happen again after your next AI-generated change unless you harden deployment and monitoring at the same time.
References
1. Roadmap.sh API Security Best Practices: https://roadmap.sh/api-security-best-practices 2. Roadmap.sh Code Review Best Practices: https://roadmap.sh/code-review-best-practices 3. Supabase Row Level Security docs: https://supabase.com/docs/guides/database/postgres/row-level-security 4. Firebase Security Rules documentation: https://firebase.google.com/docs/rules 5. Expo environment variables guide: https://docs.expo.dev/guides/environment-variables/
---
Take the next step
If this is a problem in your product right now, here is what to do next:
- [Use the free Cyprian tools](/tools) - estimate cost, score app risk, check launch readiness, or pick the right service sprint.
- [Book a discovery call](/contact) - I will tell you honestly whether you need a sprint or if you can DIY the next step.
*Written by Cyprian Tinashe Aarons - senior full-stack and AI engineer helping founders rescue, launch, automate, and scale AI-built products.*
Cyprian Tinashe Aarons — Senior Full Stack & AI Engineer
Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.