Firestore Security Rules and Supabase RLS: How LLM Prompts Close the BaaS Security Gap

Backend-as-a-Service promised to remove servers from your life. It delivered — and replaced them with a quieter problem: Firestore Security Rules and Supabase Row Level Security are now the only thing standing between your data and the open internet. Most teams get them wrong not because they are careless, but because the rules language is deceptively simple. An LLM will not fix that for you, but a well-shaped prompt will force it to expose the holes before an attacker does.

This roundup is a working set of prompts for schema design, rule authoring, query optimisation, and auth migration on Firebase and Supabase. Each one includes the reasoning behind it and a real usage example. The goal is not to let the model write your backend — it is to make the model your adversarial reviewer.

Why BaaS Rules Break in Production

A typical failure: a developer writes allow read, write: if request.auth != null; on a users collection. It passes every test because the test user is always the owner. In production, any authenticated user can read every other user's email and overwrite their profile. The rule is syntactically valid and semantically catastrophic.

The second failure is performance. Firestore charges per document read, and a query without a composite index either fails outright or silently scans. Supabase RLS policies that call a function per row turn a 10 ms query into a 2-second one under load. Neither problem shows up in development with ten documents.

The real trade-off Firebase gives you managed real-time sync and offline persistence at the cost of a proprietary query model and per-read billing. Supabase gives you Postgres and SQL at the cost of managing connection pooling and RLS complexity. Neither removes the need to understand access control.

Prompt 1: Schema Design With Access Patterns First

Most schema prompts fail because they ask for entities, not queries. Firestore has no joins, so the schema must be derived from the read patterns. This prompt forces that order.

Prompt:

You are a Firestore data modeller. Given these access patterns:

- List the 20 most recent posts in a group, paginated
- Show a user's unread notification count
- Fetch a single post with its author's display name
Design the collection structure. For each collection, list:

1. Document ID strategy (auto-ID, composite key, or UID)
2. Fields and types
3. Which queries require composite indexes
4. Which data is denormalised and what breaks when it changes
Do not propose subcollections unless a query requires them.

Example use: For a community app, the model will typically propose groups/{groupId}/posts/{postId} with a denormalised authorName on each post. That is correct for read speed but breaks when a user renames themselves. The prompt's fourth question surfaces that cost before you ship.

Prompt 2: Adversarial Firestore Security Rules Review

This is the prompt that pays for itself. Instead of asking the LLM to write rules, give it your existing rules and ask it to break them.

Prompt:

Here are my Firestore Security Rules:

[paste rules]

Act as an attacker with a valid authenticated account. List every

document I can read or write that I should not be able to. For each

finding, show the exact request path and the rule that permits it.

Then propose a corrected rule and a test case using the

Firebase Emulator Suite.

Example finding: The model will flag rules like allow write: if request.auth.uid == resource.data.ownerId; — this permits the owner to change ownerId itself, transferring the document to another user. The fix is to split create and update, and pin immutable fields:

allow update: if request.auth.uid == resource.data.ownerId

  && request.resource.data.ownerId == resource.data.ownerId;

That single line is the difference between a profile edit and an account takeover.

What to check first Run every generated rule through the Firebase Emulator with a second, non-owner user. If the emulator test does not exist, the rule does not exist.

Prompt 3: Supabase RLS Policies That Do Not Kill Performance

Supabase RLS is powerful and easy to make slow. A policy that calls auth.uid() is fine; a policy that joins to another table per row is not. This prompt separates correctness from cost.

Prompt:

Write RLS policies for these tables: [schema]. Requirements:

- Users read only their own rows in `profiles`
- Members of an `org` read all rows in `projects` where org_id matches
- Service role bypasses RLS
For each policy, state the USING and WITH CHECK clauses separately,

and flag any policy that would cause a sequential scan on a table

expected to exceed 100k rows. Suggest the index needed.

Example: For projects, the model produces:

create policy "org members read projects"

on projects for select

using ( org_id in (

  select org_id from memberships where user_id = auth.uid()

));

Then it flags that the subquery runs per row unless memberships(user_id) is indexed. Adding that index is a one-line migration that turns a table scan into an index lookup.

Prompt 4: Composite Index Generation From Query Logs

Firestore throws a FAILED_PRECONDITION error when a composite index is missing, but the error message is cryptic. Paste it in.

Prompt:

This Firestore query fails with FAILED_PRECONDITION:

[paste error]

The query is: [paste query]

Give me the exact composite index definition in firestore.indexes.json

format, and explain why the field order matters.

Example: A query where('status','==','open').orderBy('createdAt','desc') needs an index with status ascending and createdAt descending. Reversing the order makes the index useless. The model will explain that Firestore can serve an equality filter from any position but requires the orderBy field last — a rule most developers learn only after a production outage.

Prompt 5: Auth Provider Migration Checklist

Moving from Firebase Auth to Supabase Auth (or the reverse) is where user data leaks. Password hashes are not portable; sessions are not portable.

Prompt:

I am migrating users from Firebase Auth to Supabase Auth.

Produce a step-by-step plan that:

1. Preserves user UIDs or maps old to new
2. Handles users who have not logged in since migration
3. Avoids downtime for active sessions
4. Lists what cannot be migrated and the fallback for each item
Flag any step where user data could be exposed.

Example output: The model will correctly note that Firebase password hashes use a modified scrypt and cannot be imported directly into Supabase's bcrypt-based store. The practical fallback is a forced password reset on first login, triggered by a custom claim. Without this prompt, teams discover the problem after cutover.

Non-obvious insight The most dangerous rule is not the one that is too permissive — it is the one that is permissive only for unauthenticated users, because your test suite almost never runs unauthenticated.

When Firebase, When Supabase

Criterion Firebase Supabase
Real-time sync out of the box Yes Via Realtime, less mature
SQL and joins No Yes
Pricing model Per read/write Per compute/storage
Rule language Custom, limited SQL policies
Best for Mobile apps with offline needs Web apps with relational data

If your app is read-heavy and offline-first, Firebase's local cache is hard to beat. If your data is relational and your team knows SQL, Supabase removes a layer of translation. The LLM prompts above work for both, but the failure modes differ: Firestore punishes bad schema with cost, Supabase punishes bad RLS with latency.

For related reading on backend reliability and query design, see our breakdown of Go for backend with gRPC and the practical pitfalls of AI agents in production.

The Takeaway

An LLM will not secure your BaaS backend for you. But it will read your rules the way an attacker does, generate the composite index you forgot, and flag the migration step that leaks passwords. The pattern is consistent: give the model the access patterns first, ask it to break what exists, and demand a test case for every fix. That turns a vague sense of security into a checklist you can actually run.

← All posts

Ask AI about this article

Ask a question about this article — ASI Biont will answer based on its text.