Security

    Can App Store reviewers see my Supabase database content?

    An App Store Connect submitted-for-review screen beside a Supabase dashboard showing a public table with row level security disabled

    Your build is in App Review and you just realized the Supabase anon key is sitting inside the IPA. The reviewer is about to install your app, tap through the flows, and look at every screen the device renders. The question on your mind is whether the Apple reviewer can do what a curious person on the open internet can do, and read straight from your Postgres tables.

    Short answer

    Apple App Reviewers cannot read your Supabase database directly. They install your build on a managed test device and use it as a normal user, with no Apple side hook into Supabase, Firebase, or AWS. The risk you should worry about is the anon key shipped inside the IPA. According to Supabase's API key documentation, the publishable (anon) key is designed to be public, and any caller with that key plus a curl command can hit your PostgREST endpoint. If Row Level Security is off, or your policies use USING (true), every row is readable. The fix is the policy layer, not the key.

    What you should know

    • App Review is a black-box behavioral test. Reviewers install your app on a test device and only see what the UI renders. Apple has no direct API into your Supabase project.
    • The Supabase anon key is public by design. Supabase's API key reference confirms the publishable key can be bundled inside compiled mobile packages.
    • Row Level Security is the actual security boundary. Per Supabase's RLS guide, RLS must always be enabled on any table in an exposed schema.
    • A USING (true) policy provides no protection. It satisfies the RLS enabled badge but returns every row to every caller, including anonymous requests with the anon key.
    • The real risk window is after launch, not during review. Apple's reviewer is one tester. The open internet sees your endpoint the moment your app appears in TestFlight or in the store.

    Why can't App Store reviewers see Supabase data directly?

    The short answer is that App Review is a behavioral test, not a backend audit.

    Apple's App Review team works from compiled binaries uploaded to App Store Connect. The reviewer receives the IPA, installs it on a managed iPhone or iPad, and walks through the flows you advertised in the submission notes. According to Apple's App Review Guidelines, developers are required to enable backend services so they stay live during review, and to provide a demo account when the app gates content behind login. The implicit contract is that the reviewer talks to your backend through your app, the way a future user would.

    What the reviewer never receives is a credential into your Supabase, Firebase, or AWS account. Apple does not have a partnership API with Supabase that reads tables, and the App Review team does not run curl against your endpoints. The only data Apple sees is the data your screens render plus the strings their static analysis tooling extracts from the binary itself: URLs, bundled credentials, and hard-coded keys that surface under ITMS warnings like 91056 or 91053.

    That means the worst case at App Review for a Supabase-backed app is a UX rejection. A flow that does not work, a missing demo account, a feature shown in screenshots that the reviewer cannot reach. It is rarely a database disclosure.

    What can a reviewer actually extract from your IPA?

    The short answer is everything bundled inside the binary, plus whatever the app reaches over the network during the session.

    A reviewer's signed-in test device runs the same JavaScript bundle, the same React Native or Swift binaries, and the same network calls as a paying customer. Anything visible inside the IPA is visible to them, and to anyone else who downloads the app from the store. Tools like strings, Hopper, or Ghidra pull URLs, identifiers, and bundled secrets out of a binary in seconds.

    For a Supabase-backed app, the surface looks like this:

    Asset in the IPARecovery effortRisk if exposed
    Project URL (https://<ref>.supabase.co)Trivial, strings finds itNone on its own
    Publishable (anon) keyTrivial, strings finds itNone if RLS is correctly configured
    Secret or service_role keyTrivial if bundled (should never be)Total database compromise
    Stripe publishable keyTrivialNone on its own
    Stripe secret keyTrivial if bundled (should never be)Account takeover, refunds, fraud
    Internal admin endpoint URLTrivialSurface for unauthenticated probes

    The reviewer is not searching for any of this. Apple's automated layer flags some categories (Privacy Manifest violations, declared APIs without justification, certain hard-coded tokens that match known patterns), but the reviewer's session is not a security audit. The point is that the same surface is visible to every paying user, every researcher, and every curious teenager with a Mac. Apple is not the threat model worth worrying about. The open internet is.

    How does the anon key expose your Postgres tables?

    The short answer is through PostgREST, the auto-generated REST layer Supabase puts in front of every project.

    When you create a Supabase project, PostgREST is wired up automatically to expose tables in the public schema. A GET https://<ref>.supabase.co/rest/v1/<table>?select=* with the anon key in the apikey and Authorization headers returns whatever Postgres allows the anon role to read. The role's access is determined by two things: the grants on the table, and the Row Level Security policies attached to it.

    If RLS is disabled on the table, the grant alone decides access. Supabase auto-grants SELECT, INSERT, UPDATE, and DELETE to anon and authenticated on new tables created through migrations. That combination is the foot-gun. Tables created through the dashboard UI now get RLS enabled by default, but tables created through SQL migrations or third-party tools usually do not, unless the developer remembers to issue ALTER TABLE ... ENABLE ROW LEVEL SECURITY by hand.

    Take a users table created via a migration, with no RLS, holding email, hashed password, and a subscription_tier column. The following one-liner returns every row to anyone on the internet:

    curl "https://<ref>.supabase.co/rest/v1/users?select=*" \
      -H "apikey: <publishable-anon-key>" \
      -H "Authorization: Bearer <publishable-anon-key>"
    

    The same call works from a coffee shop, from a corporate proxy, from the App Review network, and from a research bot indexing new App Store releases. The data is public the second the table is created without RLS.

    What does a misconfigured RLS policy look like in practice?

    The short answer is a policy that returns rows to callers it should not.

    There are three patterns that commonly slip through, especially on AI-assisted projects where the coding agent writes the SQL without reading it back carefully.

    First, RLS is enabled but no policies exist. With RLS on and no policies, no rows are returned to anyone, including authenticated users. Developers panic, copy a snippet from a forum, and end up with the second pattern.

    Second, a permissive policy with USING (true). This policy returns every row to every caller, including unauthenticated requests on the anon role. The dashboard shows a green RLS badge, which produces a false sense of safety. According to Supabase's secure-data documentation, production policies need to compare auth.uid() against an owner column or restrict the policy to the authenticated role.

    Third, a policy with the right USING clause but a missing WITH CHECK clause for writes. Reads are filtered, but any authenticated user can insert rows that pretend to belong to a different user. This is the subtle one. A pen-tester walking the API spots it in minutes; a casual code review usually misses it.

    PatternReadsWritesReal risk
    RLS offAll callers see all rowsAll callers write any rowTotal table compromise
    USING (true)All callers see all rowsDepends on WITH CHECKRead disclosure, possible write abuse
    USING (auth.uid() = user_id) without WITH CHECKEach user reads own rowsAuthenticated users can write as anyoneIdentity fraud, cross-account writes
    USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id)Each user reads own rowsEach user writes own rowsNone for typical use

    How do you audit your Supabase project before resubmission?

    The short answer is to run the built-in Security Advisor and then probe the API yourself with the anon key.

    Supabase ships a Security Advisor inside the dashboard under Advisors then Security. The advisor flags tables with RLS disabled, policies that match USING (true), exposed functions, and unsafe extension configurations. Run it on the project tied to the build being submitted and resolve the criticals first. The advisor is not exhaustive but catches the most common misconfigurations in a single pass. Supabase documents the recommended baseline in its Securing your API guide.

    After the advisor pass, run the same probes a researcher would. From a terminal that has never opened the project before, hit the REST endpoint with the publishable key for every table you care about. For each table that returns rows without a session, ask whether that is intended. Some tables (a public products catalog, a list of supported countries, a marketing FAQ) are meant to be readable anonymously. Most are not. Then sign in as a test user and run the same call with a session JWT to verify that authenticated callers see only their own rows.

    For builders who want an external automated read of the compiled IPA and the surrounding API surface before resubmission, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning of mobile builds against OWASP MASVS, including a check on whether bundled Supabase keys correspond to an open PostgREST endpoint. The scan is observational, not a guarantee of approval, and the result is a report you read alongside your own audit.

    What to watch out for

    The first trap is treating "Apple did not flag it" as a sign the backend is safe. App Review and Postgres security are independent layers; passing one says nothing about the other. The day the app appears in the store, the IPA becomes downloadable by anyone with an Apple ID, and security tooling that watches new releases for known patterns runs against the bundle within hours.

    The second trap is rotating the anon key under the impression that secrecy fixes the problem. According to Supabase's API key documentation, the publishable key is designed to be public. Rotation moves the address; the open door stays open. The 2026 incident pattern (small AI-coded apps shipping with RLS-off tables, then having tens of thousands of user records pulled within days of launch) is consistent on this point: in every case reported on developer forums, the breach happened after launch, not during review.

    The third trap is enabling RLS on every table in a panic and forgetting to write policies. With RLS on and no policies, authenticated users see zero rows, and the app silently breaks for real customers while looking secure on the advisor.

    The fourth trap is bundling the service_role (legacy) or sb_secret_... (modern) key inside the IPA to fix the no-rows-returned problem. That key bypasses RLS by design and gives total control of the database to anyone who runs strings on the binary. Supabase's own API keys reference is explicit: secret keys must never be exposed publicly.

    Key takeaways

    • App Review does not have a backend hook into Supabase, Firebase, or AWS. Reviewers see what the app renders on a test device, nothing more.
    • The Supabase anon (publishable) key is meant to be bundled inside the IPA. Security relies on Row Level Security, not key secrecy.
    • Tables created through SQL migrations usually ship without RLS enabled. Run the Security Advisor on every project before submission and fix the criticals.
    • USING (true) is a false-positive policy. The green badge in the dashboard does not mean the table is safe; it means RLS is on with no real filter.
    • Some teams pair an internal RLS audit with an external pre-submission read of the IPA and the connected Supabase project. PTKD.com (https://ptkd.com) is one of the platforms focused on automated scanning of compiled mobile builds against OWASP MASVS before they reach App Store Connect or Google Play.
    • #security
    • #supabase
    • #rls
    • #app review
    • #anon key
    • #postgrest
    • #vibe-coded apps

    Frequently asked questions

    Does Apple inspect my Supabase project during App Review?
    No. Apple App Review has no contractual or technical hook into Supabase, Firebase, AWS, or any other backend you connect to. The reviewer installs your app from App Store Connect onto a managed test device and uses it through the normal UI. Apple can only see what your app renders, plus the strings their static analyzer pulls from the binary itself, including any keys you bundled.
    Is the Supabase anon key supposed to be public?
    Yes. According to Supabase's API key documentation, the publishable (anon) key is designed to be exposed in client code, including iOS and Android builds. Security in that model rests on Row Level Security, not key secrecy. Anyone who reverse engineers your IPA can recover the key in minutes, which is why your RLS policies do the real work.
    How can I tell if a Supabase table is exposed?
    Open the Supabase dashboard, go to the Database section, and inspect each table under the public schema. If the RLS toggle is off, the table is fully readable and writable to anyone with the anon key. Run the Security Advisor under Advisors for a project-wide report on tables and policies that fail the recommended baseline.
    What does a USING (true) RLS policy actually do?
    A policy with USING (true) returns every row to every caller, including anonymous requests with the anon key. It satisfies the RLS enabled badge in the dashboard but provides no real filtering. Production policies need to compare auth.uid() against an owner column, or restrict the policy to the authenticated role, so anonymous callers cannot read user records.
    Does an exposed Supabase database affect App Review approval?
    Apple does not directly test your RLS policies, and an open Postgres table will not, on its own, fail App Review. The risk is reputational and regulatory, not Apple side. A public breach of user emails or payment data after launch can trigger removal under Guideline 5.1.2 on data protection, plus GDPR or CCPA exposure if records were readable by anyone with curl.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free