fixes / launch-ready

How I Would Fix database rules leaking customer data in a React Native and Expo paid acquisition funnel Using Launch Ready.

If customer records are showing up where they should not, I treat it as a production incident, not a bug. In a paid acquisition funnel, that means leaked...

How I Would Fix database rules leaking customer data in a React Native and Expo paid acquisition funnel Using Launch Ready

If customer records are showing up where they should not, I treat it as a production incident, not a bug. In a paid acquisition funnel, that means leaked leads, broken trust, wasted ad spend, and possible app store or legal fallout if personal data is exposed.

The most likely root cause is bad authorization logic in the database layer or client code that is querying too broadly. The first thing I would inspect is the exact path from the Expo app to the backend: which user is authenticated, what claims they have, which collection or table is being queried, and whether row-level rules are actually enforcing tenant or ownership boundaries.

Triage in the First Hour

1. Confirm scope.

  • Identify which customer data leaked.
  • Check whether it is lead data, payment-adjacent data, profile data, or internal notes.
  • Determine if exposure is limited to authenticated users or also visible publicly.

2. Freeze risky changes.

  • Pause new deploys from Expo EAS or any CI pipeline.
  • Stop marketing spend if the funnel is still sending traffic into a broken flow.
  • Disable any admin or support accounts that may be over-privileged until reviewed.

3. Inspect logs and audit trails.

  • Review auth logs for unusual access patterns.
  • Check database access logs for broad reads on sensitive tables.
  • Look for repeated requests from the same device, IP range, or account.

4. Review the exact screens in the funnel.

  • Open signup, checkout, onboarding, and confirmation screens.
  • Verify whether any API response includes fields that should never be returned to the client.
  • Check empty states and error states too; leaks often happen there.

5. Inspect database rules and permissions.

  • Review row-level security policies or equivalent access rules.
  • Confirm whether reads are filtered by user ID, tenant ID, campaign ID, or org ID.
  • Check if service-role keys are being used in mobile code by mistake.

6. Inspect environment and secrets handling.

  • Verify production keys are not bundled into the Expo app.
  • Confirm staging and production point to different databases.
  • Check whether any secret was exposed in a public repo or build artifact.

7. Reproduce safely with test accounts only.

  • Use two non-production users with different roles or tenants.
  • Confirm what each user can read before changing anything else.
## Quick checks I would run during triage
grep -R "service_role\|admin\|secret\|SUPABASE\|FIREBASE\|API_KEY" .

Root Causes

1. Missing row-level security or equivalent access control.

  • Symptom: any authenticated user can read rows belonging to other users.
  • How to confirm: test two accounts and compare query results for cross-user visibility.

2. Overbroad client queries.

  • Symptom: the app fetches entire collections instead of scoped records.
  • How to confirm: inspect network calls and query filters in the React Native codebase.

3. Service key exposed in the mobile app or shared config.

  • Symptom: all requests behave like an admin user from the client side.
  • How to confirm: search the repo and built bundles for privileged credentials.

4. Broken tenant scoping in backend logic.

  • Symptom: policies exist, but server routes return data without checking ownership correctly.
  • How to confirm: review API handlers and compare returned rows against authenticated identity claims.

5. Misconfigured staging-to-production environment split.

  • Symptom: test users see production data because both environments point at one database.
  • How to confirm: verify every env var for API base URL, project ID, and database endpoint.

6. Weak support tooling or admin dashboard permissions.

  • Symptom: internal staff can see more than they need through dashboards or logs.
  • How to confirm: audit role-based access on internal tools and exported reports.

The Fix Plan

My approach is to narrow blast radius first, then repair authorization at the source. I do not patch this only in the app UI because UI-only fixes fail under direct API calls.

1. Lock down access immediately.

  • Disable any public read path on sensitive tables until rules are verified.
  • Rotate exposed keys if there is any chance they were shipped to clients or logged anywhere.
  • Revoke stale tokens for affected users if your auth system supports it.

2. Put authorization into the database layer first.

  • Enforce ownership checks using row-level security or strict server-side policy logic.
  • Make sure every sensitive table has explicit read and write rules.
  • Deny by default. Allow only what is needed for the current user flow.

3. Remove privileged secrets from React Native code.

  • The mobile app should never contain admin-grade credentials.
  • Move sensitive operations behind a server endpoint with least privilege access only where needed.
  • Store public config separately from secrets so builds cannot leak them.

4. Scope every query by identity and funnel context.

  • Filter by user ID plus tenant ID if you have multi-tenant behavior.
  • For paid acquisition funnels, also scope by campaign session when relevant so one lead cannot see another lead's record set.

5. Sanitize responses before they reach the device screen.

  • Return only fields required for that step in the funnel.
  • Do not send internal notes, raw metadata, payment tokens, or audit fields to mobile clients unless absolutely necessary.

6. Add defensive logging without exposing PII.

  • Log access decisions and policy failures with request IDs only.

. This helps me trace abuse without creating another privacy problem in logs.

7. Deploy in a controlled way after validation . Use a small percentage rollout if your release process supports it . If not, ship during low-traffic hours and watch error rates closely for at least 60 minutes

Regression Tests Before Redeploy

I would not redeploy until these checks pass with real test accounts:

  • Two-user isolation test:

Each account can only see its own records across signup, checkout, onboarding, and confirmation screens.

  • Unauthorized read test:

A logged-in user cannot fetch another user's record by changing an ID in a request payload or deep link.

  • Anonymous access test:

Unauthenticated requests receive deny responses on all sensitive endpoints and collections.

  • Role-based access test:

Support/admin roles can only see what their job requires, no more.

  • Build integrity test:

The production Expo build contains no service keys, debug endpoints, or hardcoded secrets.

  • Error-state test:

Failed requests do not expose raw stack traces, SQL errors, table names, emails, phone numbers, or internal IDs.

  • Funnel continuity test:

Signup conversion still works end-to-end after tightening authorization rules.

Acceptance criteria I would use:

  • Zero cross-account reads in manual testing across at least 2 separate users per role group
  • No privileged credentials present in client bundles
  • p95 API latency stays under 300 ms for core funnel reads
  • No increase in checkout abandonment after fix rollout
  • Support team can verify customer state without seeing unrelated customer records

Prevention

If I am trying to stop this from happening again, I put guardrails at four layers: code review, security controls, QA gates, and monitoring.

| Layer | Guardrail | Why it matters | | --- | --- | --- | | Code review | Require explicit auth checks on every data access path | Stops accidental broad reads | | Security | Deny-by-default policies on sensitive tables | Prevents silent exposure | | QA | Automated tests for cross-user isolation | Catches regressions before launch | | Monitoring | Alerts on unusual read volume and denied access spikes | Detects abuse early |

I also recommend these controls:

  • Add security-focused review items to pull requests:

check auth boundaries, check secret handling, check logging of PII, check dependency risk, check CORS if you have web fallback routes

  • Use realistic test cases:

one free lead, one paid lead, one refunded customer, one support agent, one admin

  • Protect conversion without weakening security:

keep signup friction low, but never let UX shortcuts bypass authorization

  • Watch performance too:

if you add heavier auth checks, verify p95 stays under target, bundle size does not bloat, and third-party scripts do not slow onboarding

When to Use Launch Ready

Launch Ready is the right sprint when you need this fixed fast without turning your product into a science project.

That matters because leaks often come with messy infrastructure too. If your funnel is already losing leads due to broken deploys weak email deliverability bad redirects or unstable environments I can clean up the launch path while fixing the security issue so you do not keep paying for traffic that lands on broken infrastructure.

What I need from you before I start:

  • Repo access for the React Native and Expo app
  • Access to your backend platform and database console
  • Current production and staging env vars
  • App store status if release is blocked
  • One short description of who should see what data
  • A list of affected screens in the funnel
  • Any recent deploys that might correlate with the leak

References

  • https://roadmap.sh/cyber-security
  • https://roadmap.sh/api-security-best-practices
  • https://roadmap.sh/qa
  • https://supabase.com/docs/guides/database/postgres/row-level-security
  • https://docs.expo.dev/build/introduction/

---

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.*

Next steps
About the author

Cyprian Tinashe AaronsSenior Full Stack & AI Engineer

Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.