Step-by-Step Guide
7 steps

How to Add Security Rules to Firebase

Firebase Security Rules are the primary mechanism for protecting your data. Without proper rules, anyone with your Firebase config can read and write your entire database. This guide covers writing, testing, and deploying rules for Firestore, Realtime Database, and Cloud Storage.

Find security issues automatically before attackers do.

Follow These Steps

1

Check your current Firestore rules

View your current rules in Firebase Console > Firestore > Rules. If they allow all access, they need to be replaced immediately.

Code Example
// INSECURE - Replace this immediately
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;  // DANGER: Anyone can read/write everything
    }
  }
}
2

Write Firestore rules scoped to authenticated users

Replace open rules with rules that restrict access to authenticated users and their own data.

Code Example
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // User profiles - only owner can read/write
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
    
    // Posts - anyone authenticated can read, only author can write
    match /posts/{postId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null 
        && request.resource.data.authorId == request.auth.uid
        && request.resource.data.keys().hasAll(['title', 'content', 'authorId']);
      allow update, delete: if request.auth != null 
        && resource.data.authorId == request.auth.uid;
    }
    
    // Deny everything else
    match /{document=**} {
      allow read, write: if false;
    }
  }
}
3

Add data validation to rules

Validate the structure and type of data being written to prevent malformed data.

Code Example
match /posts/{postId} {
  allow create: if request.auth != null
    && request.resource.data.title is string
    && request.resource.data.title.size() > 0
    && request.resource.data.title.size() <= 200
    && request.resource.data.content is string
    && request.resource.data.content.size() <= 50000
    && request.resource.data.authorId == request.auth.uid
    && request.resource.data.createdAt == request.time;
}
4

Write Storage Security Rules

Restrict file uploads by user, file type, and file size.

Code Example
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/{fileName} {
      allow read: if request.auth != null;
      allow write: if request.auth != null
        && request.auth.uid == userId
        && request.resource.size < 5 * 1024 * 1024
        && request.resource.contentType.matches('image/.*');
    }
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}
5

Test rules with the Firebase Emulator

Use the Firebase Emulator Suite to test rules locally before deploying.

Code Example
# Start the emulator
firebase emulators:start

# Run rules tests
npm test

// Test file example
import { assertSucceeds, assertFails } from '@firebase/rules-unit-testing'

it('allows user to read own profile', async () => {
  const db = getFirestore({ uid: 'user1' })
  await assertSucceeds(db.collection('users').doc('user1').get())
})

it('denies reading other profiles', async () => {
  const db = getFirestore({ uid: 'user1' })
  await assertFails(db.collection('users').doc('user2').get())
})
6

Deploy your rules

Deploy rules to production after testing.

Code Example
# Deploy all rules
firebase deploy --only firestore:rules,storage

# Deploy specific service rules
firebase deploy --only firestore:rules
7

Scan your deployed app

Run a VAS scan to verify rules are enforced and no data is publicly accessible.

What You'll Achieve

Firestore, Realtime Database, and Storage all have restrictive Security Rules. Data access is scoped to authenticated users, write operations validate data structure, and file uploads are restricted by type and size.

Common Mistakes to Avoid

Mistake

Using allow read, write: if true in production

Fix

This gives anyone full access. Replace with rules that check request.auth and scope to user-owned resources.

Mistake

Not adding a catch-all deny rule

Fix

Add match /{document=**} { allow read, write: if false; } at the end to deny access to any paths not explicitly allowed.

Mistake

Forgetting to validate data structure in rules

Fix

Add type checks and required field validation in create rules. This prevents malformed data from entering your database.

Frequently Asked Questions

Can I test Security Rules without deploying?

Yes. Use the Firebase Emulator Suite to run and test rules locally. The @firebase/rules-unit-testing package lets you write automated tests for your rules.

Do Security Rules affect Admin SDK operations?

No. The Firebase Admin SDK bypasses all Security Rules. Rules only apply to client SDK requests. This is why Admin SDK must only be used in trusted server environments.

How do rules handle nested subcollections?

Each collection path needs its own rules. A rule on /users/{userId} does not automatically apply to /users/{userId}/posts/{postId}. Define rules for each path explicitly.

Ready to Secure Your App?

VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.

Start Security Scan