Skip to main content
This is the full reference for everything you can use inside Lark security rule expressions. If you’re new to rules, start with the security rules overview first.

Variables

These variables are available in every rule expression.
VariableTypeDescription
authobject | nullThe authenticated user. null if the client is unauthenticated.
auth.uidstringThe unique ID of the authenticated user.
auth.providerstringThe authentication provider (e.g., "google", "anonymous", "password", "facebook", "github", "twitter").
auth.tokenobjectThe contents of the auth token, including any custom claims.
datasnapshotA snapshot of the current data at this path, before the write.
newDatasnapshotA snapshot of the data that would exist after the write. The merged result of new data and existing data. Only available in .write and .validate rules.
rootsnapshotA snapshot of the root of the entire database. Use this to read data at other paths.
nownumberThe current server timestamp in milliseconds since epoch.
$wildcardsstringPath segment captures. For example, a rule at /users/$userId makes $userId available as a string variable containing the matched key.
data and newData are scoped to the current path where the rule is defined. Use root when you need to look up data elsewhere in your database.

Snapshot methods

The data, newData, and root variables are all snapshots. You can call these methods on any snapshot.
MethodReturnsDescription
val()anyReturns the primitive value (string, number, boolean, null) at this snapshot. For snapshots with children, use child() to access nested values.
exists()booleanReturns true if this snapshot contains any data. Equivalent to val() != null.
hasChild(path)booleanReturns true if the specified child path exists. path can be a single key or a slash-separated path.
hasChildren(keys)booleanReturns true if all of the specified child keys exist. keys is an array of strings. With no arguments, returns true if the snapshot has any children.
parent()snapshotReturns a snapshot of the parent node. Fails if called on the root.
child(path)snapshotReturns a snapshot of the child at the given path. path can be a single key or a deeper slash-separated path (e.g., 'address/city'). If the child doesn’t exist, returns an empty snapshot.
getPriority()string | number | nullReturns the priority of the data at this snapshot.
isString()booleanReturns true if the value is a string.
isNumber()booleanReturns true if the value is a number.
isBoolean()booleanReturns true if the value is a boolean.

Examples

// Check if the current data exists
data.exists()

// Check if the incoming data has both 'name' and 'score' children
newData.hasChildren(['name', 'score'])

// Read a sibling value
data.parent().child('status').val() === 'active'

// Look up data at another path entirely
root.child('admins/' + auth.uid).exists()

// Check a deeply nested child
data.child('stats/hp').val() > 0

// Type-check incoming data
newData.child('name').isString() && newData.child('score').isNumber()

String methods

These methods are available on any string value in a rule expression, including auth.uid, $wildcard captures, and string values returned by val().
Method / PropertyReturnsDescription
lengthnumberThe length of the string. This is a property, not a method — no parentheses.
contains(substring)booleanReturns true if the string contains the given substring.
beginsWith(substring)booleanReturns true if the string starts with the given prefix.
endsWith(substring)booleanReturns true if the string ends with the given suffix.
replace(substring, replacement)stringReturns a copy of the string with all instances of substring replaced by replacement.
toLowerCase()stringReturns the string converted to lower case.
toUpperCase()stringReturns the string converted to upper case.
matches(regex)booleanReturns true if the string matches the given regular expression.

Examples

// Validate that a username is at least 3 characters
newData.child('username').val().length >= 3

// Check that an email looks valid
newData.child('email').val().matches(/^[^@]+@[^@]+\.[^@]+$/)

// Check a string prefix
auth.token.identifier.beginsWith('internal-')

// Escape periods for use as keys
newData.child('email').val().replace('.', '%2E')

// Case-insensitive lookup
root.child('users').child(auth.token.identifier.toLowerCase()).exists()

Operators

Standard operators work inside rule expressions.

Comparison

OperatorDescription
===Strict equality (type and value)
!==Strict inequality
<Less than
>Greater than
<=Less than or equal to
>=Greater than or equal to
== is treated as === and != is treated as !== in rules. Both are strict comparisons — there is no loose equality.

Logical

OperatorDescription
&&Logical AND
||Logical OR
!Logical NOT

Arithmetic

OperatorDescription
+Addition (also string concatenation)
-Subtraction / negation
*Multiplication
/Division
%Modulo

Ternary

OperatorDescription
? :Conditional expression. condition ? valueIfTrue : valueIfFalse
Use the + operator to build dynamic paths for child() lookups: root.child('users/' + auth.uid + '/role').val() === 'admin'.

Query-based rules

You can restrict what queries clients are allowed to run by referencing query. expressions in your rules. This lets you enforce that clients include certain filters or limits.

Query variables

ExpressionTypeDescription
query.orderByKeybooleantrue if the query is ordered by key.
query.orderByPrioritybooleantrue if the query is ordered by priority.
query.orderByValuebooleantrue if the query is ordered by value.
query.orderByChildstring | nullThe child key being ordered by, or null if not ordered by a child.
query.startAtstring | number | boolean | nullThe start bound of the query, or null if none.
query.endAtstring | number | boolean | nullThe end bound of the query, or null if none.
query.equalTostring | number | boolean | nullThe equality filter of the query, or null if none.
query.limitToFirstnumber | nullThe limit-to-first value, or null if none.
query.limitToLastnumber | nullThe limit-to-last value, or null if none.

Examples

Restrict access to a collection so clients can only read their own items:
{
  "rules": {
    "baskets": {
      ".read": "auth.uid !== null &&
                query.orderByChild === 'owner' &&
                query.equalTo === auth.uid"
    }
  }
}
A query that includes the required parameters succeeds:
db.ref('baskets')
  .orderByChild('owner')
  .equalTo(auth.currentUser.uid)
  .on('value', callback); // Succeeds
A query without the parameters fails:
db.ref('baskets')
  .on('value', callback); // PERMISSION_DENIED
Limit how much data a client can download:
{
  "rules": {
    "messages": {
      ".read": "query.orderByKey && query.limitToFirst <= 1000"
    }
  }
}

What’s next