How Security Rules work

Security can be one of the most complex pieces of the app development puzzle.In most applications, developers must build and run a server thathandles authentication (who a user is) and authorization (what a user can do).

Firebase Security Rules remove the middle (server) layer and allow you to specify path-basedpermissions for clients that connect to your data directly. Use this guide tolearn more about how rules are applied to incoming requests.

Select a product to learn more about its rules.

Cloud Firestore

Basic structure

Firebase Security Rules inCloud Firestore andCloud Storage use the following structure andsyntax:

service <<name>> {  // Match the resource path.  match <<path>> {    // Allow the request if the following conditions are true.    allow <<methods>> : if <<condition>>  }}

The following key concepts are important to understand as you build the rules:

  • Request: The method or methods invoked in theallow statement. These aremethods you're allowing to run. The standard methods are:get,list,create,update, anddelete. Theread andwrite convenience methodsenable broad read and write access on the specified database or storage path.
  • Path: The database or storage location, represented as aURI path.
  • Rule: Theallow statement, which includes a condition that permits arequest if it evaluates to true.

Security rules version 2

As of May 2019, version 2 of theFirebase security rules is nowavailable. Version 2 of the rules changes the behavior ofrecursivewildcards{name=**}. You must use version 2 if you plan tousecollection group queries. You must opt-in toversion 2 by makingrules_version = '2'; the first line in your securityrules:

rules_version = '2';service cloud.firestore {  match /databases/{database}/documents {
Avoid using recursive wildcards unless you intend forpermissive security rules to propagate to all nested subcollections.

Matching paths

All match statements should point to documents, not collections. A matchstatement can point to a specific document, as inmatch /cities/SF or use wildcardsto point to any document in the specified path, as inmatch /cities/{city}.

In the example, the match statement uses the{city} wildcard syntax.This means the rule applies to any document in thecities collection, such as/cities/SF or/cities/NYC. When theallow expressions in the match statement areevaluated, thecity variable will resolve to the city document name,such asSF orNYC.

Note: You can only access documents that your security rules specifically allowyou to access. For example, the rules shown allow access only to documentsin thecities collection; as a result, they also deny access to documents inall other collections.

Matching subcollections

Data inCloud Firestore is organized into collections of documents, and eachdocument may extend the hierarchy through subcollections. It is important tounderstand how security rules interact with hierarchical data.

Consider the situation where each document in thecities collection contains alandmarks subcollection. Security rules apply only at the matched path, so theaccess controls defined on thecities collection don't apply to thelandmarks subcollection. Instead, write explicit rules to control accessto subcollections:

servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}{     allowread,write:if<condition>;//Explicitlydefinerulesforthe'landmarks'subcollection     match/landmarks/{landmark}{       allowread,write:if<condition>;   }   } }}

When nestingmatch statements, the path of the innermatch statement is alwaysrelative to the path of the outermatch statement. The following rulesetsare therefore equivalent:

servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}{   match/landmarks/{landmark}{     allowread,write:if<condition>;     }   } }}
servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}/landmarks/{landmark}{   allowread,write:if<condition>;   } }}

Overlapping match statements

It's possible for a document to match more than onematch statement. In thecase where multipleallow expressions match a request, the access is allowedifany of the conditions istrue:

servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthe'cities'collection.match/cities/{city}{allowread,write:iffalse;}//Matchesanydocumentinthe'cities'collection.match/cities/{document}{allowread,write:iftrue;}}}

In the example, all reads and writes to thecities collection will beallowed because the second rule is alwaystrue, even though the firstrule is alwaysfalse.

Recursive wildcards

If you want rules to apply to an arbitrarily deep hierarchy, use therecursive wildcard syntax,{name=**}:

servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthecitiescollectionaswellasanydocument//inasubcollection.match/cities/{document=**}{allowread,write:if<condition>;}}}

When using the recursive wildcard syntax, the wildcard variable will contain theentire matching path segment, even if the document is located in a deeply nestedsubcollection. For example, the rules listed would matcha document located at/cities/SF/landmarks/coit_tower, and the value ofthedocument variable would beSF/landmarks/coit_tower.

Note, however, that the behavior of recursive wildcards depends on the rulesversion.

Version 1

Security rules use version 1 by default. In version 1, recursive wildcardsmatch one or more path items. They don't match an empty path, somatch /cities/{city}/{document=**} matches documents in subcollections butnot in thecities collection, whereasmatch /cities/{document=**} matchesboth documents in thecities collection and subcollections.

Recursive wildcards must come at the end of a match statement.

Version 2

In version 2 of the security rules, recursive wildcards match zero or more pathitems.match/cities/{city}/{document=**} matches documents in anysubcollections as well as documents in thecities collection.

You must opt-in to version 2 by addingrules_version = '2'; at the top ofyour security rules:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthecitiescollectionaswellasanydocument//inasubcollection.match/cities/{city}/{document=**}{allowread,write:if<condition>;}}}

You can have at most one recursive wildcard per match statement, but in version2, you can place this wildcard anywhere in the match statement. For example:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthesongscollectiongroupmatch/{path=**}/songs/{song}{allowread,write:if<condition>;}}}

If you usecollection group queries, you must useversion 2, seesecuring collection group queries.

Security rule limits

As you work with security rules, note the following limits:

LimitDetails
Maximum number ofexists(),get(), andgetAfter() calls per request
  • 10 for single-document requests and query requests.
  • 20 for multi-document reads, transactions, and batched writes. The previous limit of 10 also applies to each operation.

    For example, imagine you create a batched write request with 3 write operations and that your security rules use 2 document access calls to validate each write. In this case, each write uses 2 of its 10 access calls and the batched write request uses 6 of its 20 access calls.

Exceeding either limit results in a permission denied error.

Some document access calls may be cached, and cached calls do not count towards the limits.

Maximum nestedmatch statement depth10
Maximum path length, in path segments, allowed within a set of nestedmatch statements100
Maximum number of path capture variables allowed within a set of nestedmatch statements20
Maximum function call depth20
Maximum number of function arguments7
Maximum number oflet variable bindings per function10
Maximum number of recursive or cyclical function calls0 (not permitted)
Maximum number of expressions evaluated per request1,000
Maximum size of a rulesetRulesets must obey two size limits:
  • a 256 KB limit on the size of the ruleset text source published from theFirebase console or from the CLI usingfirebase deploy.
  • a 250 KB limit on the size of the compiled ruleset that results when Firebase processes the source and makes it active on the back-end.

Cloud Storage

Basic structure

Firebase Security Rules inCloud Firestore andCloud Storage use the following structure andsyntax:

service <<name>> {  // Match the resource path.  match <<path>> {    // Allow the request if the following conditions are true.    allow <<methods>> : if <<condition>>  }}

The following key concepts are important to understand as you build the rules:

  • Request: The method or methods invoked in theallow statement. These aremethods you're allowing to run. The standard methods are:get,list,create,update, anddelete. Theread andwrite convenience methodsenable broad read and write access on the specified database or storage path.
  • Path: The database or storage location, represented as aURI path.
  • Rule: Theallow statement, which includes a condition that permits arequest if it evaluates to true.

Matching paths

Cloud Storage Security Rulesmatch the file paths used to access files inCloud Storage. Rules canmatch exact paths or wildcard paths, andrules can also be nested. If no match rule allows an request method, or thecondition evaluates tofalse, the request is denied.

Exact matches

// Exact match for "images/profilePhoto.png"match/images/profilePhoto.png{allowwrite:if<condition>;}// Exact match for "images/croppedProfilePhoto.png"match/images/croppedProfilePhoto.png{allowwrite:if<other_condition>;}

Nested matches

// Partial match for files that start with "images"match/images{// Exact match for "images/profilePhoto.png"match/profilePhoto.png{allowwrite:if<condition>;}// Exact match for "images/croppedProfilePhoto.png"match/croppedProfilePhoto.png{allowwrite:if<other_condition>;}}

Wildcard matches

Rules can also be used tomatch a pattern using wildcards. A wildcard is anamed variable that represents either a single string such asprofilePhoto.png, or multiple path segments, such asimages/profilePhoto.png.

A wildcard is created by adding curly braces around the wildcard name, like{string}. A multiple segment wildcard can be declared by adding=** to thewildcard name, like{path=**}:

Avoid using recursive wildcards unless you intend forpermissive security rules to propagate to all nested folders.
// Partial match for files that start with "images"match/images{// Exact match for "images/*"// e.g. images/profilePhoto.png is matchedmatch/{imageId}{// This rule only matches a single path segment (*)// imageId is a string that contains the specific segment matchedallowread:if<condition>;}// Exact match for "images/**"// e.g. images/users/user:12345/profilePhoto.png is matched// images/profilePhoto.png is also matched!match/{allImages=**}{// This rule matches one or more path segments (**)// allImages is a path that contains all segments matchedallowread:if<other_condition>;}}

If multiple rules match a file, the result is theOR of the result of allrules evaluations. That is, if any rule the file matches evaluates totrue, theresult istrue.

In the rules, the file "images/profilePhoto.png" can be read if eithercondition orother_condition evaluate to true, while the file"images/users/user:12345/profilePhoto.png" is only subject to the result ofother_condition.

A wildcard variable can be referenced from within thematch provide filename or path authorization:

// Another way to restrict the name of a filematch/images/{imageId}{allowread:ifimageId=="profilePhoto.png";}

Cloud Storage Security Rules don't cascade, and rules are only evaluated when therequest path matches a path with rules specified.

Request evaluation

Uploads, downloads, metadata changes, and deletes are evaluated using therequest sent toCloud Storage. Therequest variable contains thepath where the request is being performed, the time when the request isreceived, and the newresource value if the request is a write. HTTP headersand authentication state are also included.

Therequest object also contains the user's unique ID and theFirebase Authentication payload in therequest.auth object, which will beexplained further in theAuthenticationsection of the docs.

A full list of properties in therequest object is available below:

PropertyTypeDescription
authmap<string, string>When a user is logged in, providesuid, the user's unique ID, andtoken, a map ofFirebase Authentication JWT claims. Otherwise, it will benull.
paramsmap<string, string>Map containing the query parameters of the request.
pathpathApath representing the path the request is being performed at.
resourcemap<string, string>The new resource value, present only onwrite requests.
timetimestampA timestamp representing the server time the request is evaluated at.
Note: Detailed documentation for these properties is available in theFirebase Security Rules forCloud Storage APIreference.

Resource evaluation

When evaluating rules, you may also want to evaluate the metadata of the filebeing uploaded, downloaded, modified, or deleted. This lets you createcomplex and powerful rules that do things like only allow files with certaincontent types to be uploaded, or only files greater than a certain size to bedeleted.

Firebase Security Rules forCloud Storage provides file metadata in theresourceobject, which contains key/value pairs of the metadata surfaced in aCloud Storage object. These properties can be inspected onread orwrite requests to ensure data integrity.

Onwrite requests (such as uploads, metadata updates, and deletes), inaddition to theresource object, which contains file metadata for the filethat exists at the request path, you also have the ability to use therequest.resource object, which contains a subset of the file metadata to bewritten if the write is allowed. You can use these two values to ensure dataintegrity or enforce application constraints such as file type or size.

A full list of properties in theresource object is available:

PropertyTypeDescription
namestringThe full name of the object
bucketstringThe name of the bucket this object resides in.
generationintTheGoogle Cloud Storage object generation of this object.
metagenerationintTheGoogle Cloud Storage object meta generation of this object.
sizeintThe size of the object in bytes.
timeCreatedtimestampA timestamp representing the time an object was created.
updatedtimestampA timestamp representing the time an object was last updated.
md5HashstringAn MD5 hash of the object.
crc32cstringA crc32c hash of the object.
etagstringThe etag associated with this object.
contentDispositionstringThe content disposition associated with this object.
contentEncodingstringThe content encoding associated with this object.
contentLanguagestringThe content language associated with this object.
contentTypestringThe content type associated with this object.
metadatamap<string, string>Key/value pairs of additional, developer specified custom metadata.

request.resource contains all of these with the exception ofgeneration,metageneration,etag,timeCreated, andupdated.

Note: Detailed documentation for these properties is available in theFirebase Security Rules forCloud Storage APIreference.

Security Rules limits

As you work with security rules, note the following limits:

LimitDetails
Maximum number offirestore.exists() andfirestore.get() calls per request

2 for single-document requests and query requests.

Exceeding this limit results in a permission denied error.

Access calls to the same documents may be cached, and cached calls don't count towards the limits.

Full Example

Putting it all together, you can create a full example of rules for an imagestorage solution:

servicefirebase.storage{match/b/{bucket}/o{match/images{//Allowwritefilestothepath"images/*",subjecttotheconstraints://1)Fileislessthan5MB//2)Contenttypeisanimage//3)Uploadedcontenttypematchesexistingcontenttype//4)Filename(storedinimageIdwildcardvariable)islessthan32charactersmatch/{imageId}{allowread;allowwrite:ifrequest.resource.size <5*1024*1024                    &&request.resource.contentType.matches('image/.*')                    &&request.resource.contentType==resource.contentType                    &&imageId.size() <32}}}}

Realtime Database

Basic structure

InRealtime Database,Firebase Security Rules consist of JavaScript-like expressions contained in aJSON document.

They use the following syntax:

{  "rules": {    "<<path>>": {    // Allow the request if the condition for each method is true.      ".read": <<condition>>,      ".write": <<condition>>,      ".validate": <<condition>>    }  }}

There are three basic elements in the rule:

  • Path: The database location. This mirrors your database's JSON structure.
  • Request: These are the methods the rule uses to grant access. Thereadandwrite rules grant broad read and write access, whilevalidate rulesact as a secondary verification to grant access based on incoming or existingdata.
  • Condition: The condition that permits a request if it evaluates to true.

How rules apply to paths

InRealtime Database,Security Rules apply atomically, meaning that rules athigher-level parent nodes override rules at more granular child nodes andrules at a deeper node can't grant access to a parent path. Youcan't refine or revoke access at a deeper path in your database structure ifyou've already granted it for one of the parent paths.

Consider the following rules:

{  "rules": {     "foo": {        // allows read to /foo/*        ".read": "data.child('baz').val() === true",        "bar": {          // ignored, since read was allowed already          ".read": false        }     }  }}

This security structure allows/bar/ to be read from whenever/foo/ contains a childbaz with valuetrue.The".read": false rule under/foo/bar/ has noeffect here, since access cannot be revoked by a child path.

While it may not seem immediately intuitive, this is a powerful part of therules language and allows for very complex access privileges to be implementedwith minimal effort. This is particularly useful foruser-based security.

However,.validate rules do not cascade. All validate rulesmust be satisfied at all levels of the hierarchy for a write to be allowed.

Additionally, because rules do not apply back to a parent path, read or writeoperation fail if there isn't a rule at the requested location or at a parentlocation that grants access. Even if every affected child path is accessible,reading at the parent location will fail completely. Consider this structure:

{  "rules": {    "records": {      "rec1": {        ".read": true      },      "rec2": {        ".read": false      }    }  }}

Without understanding that rules are evaluated atomically, it might seemlike fetching the/records/ path would returnrec1but notrec2. The actual result, however, is an error:

JavaScript
vardb=firebase.database();db.ref("records").once("value",function(snap){//successmethodisnotcalled},function(err){//errorcallbacktriggeredwithPERMISSION_DENIED});
Objective-C
Note: This Firebase product is not available on the App Clip target.
FIRDatabaseReference*ref=[[FIRDatabasedatabase]reference];[[_refchild:@"records"]observeSingleEventOfType:FIRDataEventTypeValuewithBlock:^(FIRDataSnapshot*snapshot){// success block is not called}withCancelBlock:^(NSError*_Nonnullerror){// cancel block triggered with PERMISSION_DENIED}];
Swift
Note: This Firebase product is not available on the App Clip target.
varref=FIRDatabase.database().reference()ref.child("records").observeSingleEventOfType(.Value,withBlock:{snapshotin// success block is not called},withCancelBlock:{errorin// cancel block triggered with PERMISSION_DENIED})
Java
FirebaseDatabasedatabase=FirebaseDatabase.getInstance();DatabaseReferenceref=database.getReference("records");ref.addListenerForSingleValueEvent(newValueEventListener(){@OverridepublicvoidonDataChange(DataSnapshotsnapshot){// success method is not called}@OverridepublicvoidonCancelled(FirebaseErrorfirebaseError){// error callback triggered with PERMISSION_DENIED});});
REST
curl https://docs-examples.firebaseio.com/rest/records/# response returns a PERMISSION_DENIED error

Since the read operation at/records/ is atomic, and there's no read rule that grants access to all of the data under/records/, this will throw aPERMISSION_DENIED error. If we evaluate this rule in the security simulator in ourFirebase console, we can see that the read operation was denied:

Attempt to read /records with auth=Success(null)    /    /recordsNo .read rule allowed the operation.Read was denied.

The operation was denied because no read rule allowed access to the/records/ path, but note that the rule forrec1 was never evaluated because it wasn't in the path we requested. To fetchrec1, we would need to access it directly:

JavaScript
vardb=firebase.database();db.ref("records/rec1").once("value",function(snap){// SUCCESS!},function(err){// error callback is not called});
Objective-C
Note: This Firebase product is not available on the App Clip target.
FIRDatabaseReference*ref=[[FIRDatabasedatabase]reference];[[refchild:@"records/rec1"]observeSingleEventOfType:FEventTypeValuewithBlock:^(FIRDataSnapshot*snapshot){// SUCCESS!}];
Swift
Note: This Firebase product is not available on the App Clip target.
varref=FIRDatabase.database().reference()ref.child("records/rec1").observeSingleEventOfType(.Value,withBlock:{snapshotin// SUCCESS!})
Java
FirebaseDatabasedatabase=FirebaseDatabase.getInstance();DatabaseReferenceref=database.getReference("records/rec1");ref.addListenerForSingleValueEvent(newValueEventListener(){@OverridepublicvoidonDataChange(DataSnapshotsnapshot){// SUCCESS!}@OverridepublicvoidonCancelled(FirebaseErrorfirebaseError){// error callback is not called}});
REST
curl https://docs-examples.firebaseio.com/rest/records/rec1# SUCCESS!

Location variable

Realtime DatabaseSecurity Rules support a$locationvariable to match path segments. Use the$ prefix in front of your pathsegment to match your rule to any child nodes along the path.

{"rules":{"rooms":{//Thisruleappliestoanychildof/rooms/,thekeyforeachroomid//isstoredinside$room_idvariableforreference"$room_id":{"topic":{//Theroom's topic can be changed if the room id has "public" in it".write":"$room_id.contains('public')"}}}}}

You can also use the$variable in parallel with constant pathnames.

  {    "rules": {      "widget": {        // a widget can have a title or color attribute        "title": { ".validate": true },        "color": { ".validate": true },        // but no other child paths are allowed        // in this case, $other means any key excluding "title" and "color"        "$other": { ".validate": false }      }    }  }

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-18 UTC.