Firebase Security Rules for AI-Built Apps: Copy-Paste Templates
Copy-paste Firebase security rules templates for AI-built apps: owner-only docs, public-read content, auth-only collections, and locked Storage rules.
You know your Firebase Security Rules are wrong, or at least unproven. What you actually want isn't another list of mistakes to avoid: it's something to paste in and ship. This post is that: real, working Firestore and Storage rules templates for the patterns almost every AI-built app needs, explained line by line so you can adapt them without writing a rule from scratch.
Security Rules are the rulebook Google runs on every read and write to your Firestore database and Storage bucket. Because a Firebase app talks straight from the browser to Google with no server in between to check permissions, the rules are your access control. If you already want the catalog of ways AI tools get this wrong first, read Firebase Security Rules: 12 mistakes AI tools make. This post picks up from there and gives you the rules themselves.
⚡ TL;DR
- Four templates below cover almost every vibe-coded app: owner-only documents, public-read/owner-write content, sign-in-required collections, and locked Storage files.
- The one line that does the real work in every template is an ownership check:
request.auth.uid == resource.data.ownerIdor similar, not just "is someone logged in."- Paste these into the Firebase Console's Rules tab, swap the field names for your own schema, and hand the whole thing to your AI builder as a prompt to adapt it automatically.
Template 1: users can only read/write their own document
The most common pattern in any app with accounts: a /users/{userId} collection where each person should see and edit only their own profile, settings, or account record.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
What each line does:
request.auth != null: the request must come from a signed-in user.request.authis the object Firebase fills in with the caller's identity; if nobody's logged in, it's empty.request.auth.uid == userId: the logged-in user's unique ID (uid) must match the{userId}in the document's path. This is the ownership check. Without it, any logged-in account could read or write anyone's profile.- Together: only the account that owns this exact document gets in. Everyone else, logged in or not, is denied.
This same shape works for any collection keyed by the owner's uid in the path itself: settings, private notes, saved preferences.
Template 2: public read, owner-only write (a posts/content collection)
For a blog, feed, or public listings where anyone should be able to see the content, but only the author should be able to change or delete it:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if true;
allow create: if request.auth != null
&& request.auth.uid == request.resource.data.authorId;
allow update, delete: if request.auth != null
&& request.auth.uid == resource.data.authorId;
}
}
}
What each line does:
allow read: if true: anyone, logged in or not, can view posts. This is a deliberate public-read rule, not the dangerousallow read, write: if trueyou'll see flagged elsewhere. The difference is that write is locked down separately below.allow create: … request.resource.data.authorId: on a brand-new document,request.resource.datais the incoming data being written. This line requires the new post'sauthorIdfield to match the signed-in user'suid, so people can only create posts under their own name.allow update, delete: … resource.data.authorId: on an existing document,resource.datais the data already stored. This requires the existing post's author to match the caller before they can edit or delete it. So nobody can edit someone else's post.
Swap posts/authorId for whatever your collection and owner field are actually called: a marketplace listing, a recipe, a public profile.
Template 3: authenticated users only (a generic shared collection)
For collections that shouldn't be public, but every signed-in user is allowed to read and write freely (a shared team wiki, a comments thread where any member can post), no per-document ownership is needed:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /shared-notes/{noteId} {
allow read, write: if request.auth != null;
}
}
}
Use this one carefully. request.auth != null only proves someone is logged in; it does not stop one signed-in user from editing or deleting another's entry. That's fine for a truly shared space (a team of trusted members), but it's the exact rule flagged as mistake #3 in our mistakes post when it's applied to data that should be private per user. If each person's data should stay theirs, use Template 1 instead.
Template 4: Storage rules gated on the file's owner
Firestore rules and Storage rules are two separate rulebooks. Locking your database does nothing for your file bucket. For user uploads (avatars, documents, photos), gate access on a uid folder structure:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /user-uploads/{userId}/{fileName} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
What each line does:
match /user-uploads/{userId}/{fileName}: this rule only applies to files stored under a path likeuser-uploads/abc123/photo.jpg, whereabc123is the owner'suid. Your upload code needs to actually write files into that structure for the rule to mean anything.request.auth.uid == userId: same ownership check as Template 1, applied to files instead of documents.
If your app instead stores an owner ID inside the file's own metadata rather than its path, you can check that directly: request.auth.uid == resource.metadata.owner. Here, resource.metadata is a custom key-value pair you set at upload time. Either approach works; pick whichever matches how your AI builder actually structured the uploads.
Not sure if your app has this exact issue?
Run a free, read-only scan of your live app: no install, results in under a minute.
Scan my app free →Turning a template into a prompt for your AI builder
You don't have to hand-edit these templates yourself. The faster path for most non-developers is to describe your actual schema and let your AI builder adapt the template correctly. A prompt that works well:
"Here is a Firestore/Storage Security Rules template for [owner-only documents / public-read content / Storage files gated by owner]. My collection is called [your collection name], and the field that stores who owns each document is called [your field name]. Adapt this template to my exact collection and field names, keep the ownership check on every read and write that should be private, and don't add any allow read, write: if true fallback rule. Show me the full rules file so I can paste it into the Firebase Console myself."
Naming your real collection and owner field matters. A generic "please secure my Firebase rules" prompt is exactly what produces the vague, over-permissive rules covered in our mistakes post. Being specific here is what gets you a rule you can trust.
After the AI hands the rules back, paste them into Firebase Console → Firestore (or Storage) → Rules, and read them once yourself: every collection that holds one person's data should end in an ownership check, not just request.auth != null.
FAQ
Can I just copy one of these templates directly into my app?
You can paste it in as a starting point, but the collection and field names (users, authorId, ownerId) need to match your actual schema exactly, or the rule silently protects nothing. Check your Firestore data structure first, then swap in your real names.
Do I need different rules for Firestore and Realtime Database?
Yes, syntax differs, though the logic (ownership checks over blanket access) is the same idea. These templates are written for Firestore, which is the default for most new Firebase projects and what most AI builders scaffold.
What's the difference between resource.data and request.resource.data?
resource.data is the document as it already exists in the database, before this request. request.resource.data is the incoming data from the current write. You use request.resource.data when checking a new document being created (there's no existing document yet) and resource.data when checking an existing one before an update or delete.
The bottom line
You don't need to write Firebase Security Rules from scratch to get them right, but you do need rules that check ownership, not just login, on anything that isn't meant to be public. Start from the template that matches your collection, name your real fields when you hand it to your AI builder, and read the result back before you ship it. An attacker can test your rules for gaps in minutes; your job is to close them first, and to re-check every time your AI adds a new collection or upload path.
Find your gaps before an attacker does.
Is My Site Hackable? scans your deployed app for the exact issues in this article (exposed keys, missing RLS, open buckets) and tells you what's real and what's a false alarm.
Run a free scan →