Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore security rule: cost of using request.resource.data.__field__ != resource.data.__field__?

Is it costly (i.e. roughly how many reads & how much are we charged in $) to have a firestore security like this:

 match /profiles/{document=**} {
   allow create: if request.auth.uid != null
   && (request.resource.data.firstName is string && resource.data.firstName != request.resource.data.firstName)
   && (request.resource.data.lastName is string && resource.data.firstName != request.resource.data.firstName)
  && (request.resource.data.username is string && resource.data.username != request.resource.data.username)
  && (request.resource.data.email is string && resource.data.email != request.resource.data.email)
}
like image 882
Jek Avatar asked Nov 01 '25 19:11

Jek


2 Answers

According to the documentation, you are billed for get() and exists() requests in your security rules:

Using the get() and exists() functions, your security rules can evaluate incoming requests against other documents in the database.

Continued:

Using these functions executes a read operation in your database, which means you will be billed for reading documents even if your rules reject the request. See Cloud Firestore Pricing for more specific billing information.

So, if your rules don't use get() or exists(), then you don't have additional billing associated with the rules. It appears you are not using either of those functions here, so I would anticipate no additional billing.

like image 57
Doug Stevenson Avatar answered Nov 03 '25 20:11

Doug Stevenson


I just tested out this simple security rule:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    function isAuthor() {
      return request.auth != null &&
             request.auth.uid == resource.data.author.uuid;
    }
    match /posts/{postId} {
      allow read, write: if isAuthor();
    }
  }
}

With a simulated read operation and an "incorrect" UID, I read a document 100 times and it was denied 100, and it counted towards the billing 100 times as read operations as you can see in this spike.

A huge spike of 100 sudden read operations despite the security rule denying the request

So Yes, using resource is costly. No matter if it is denied or passed, it'd count towards your billing and you are subject to billing fraud due to Firebase's naturally amazing system.

You'd need to implement a lot of cloud workarounds to mitigate this in production with many users since there's no straight solution or one way to protect against such attacks.

Edit:

Official Firebase Docs says

The resource is the current value within the service represented as a map of key-value pairs. Referencing resource within a condition will result in at most one read of the value from the service. This lookup will count against any service-related quota for the resource. For get requests, the resource will only count toward quota on deny.

That means that if your condition does not reference resource, it will not get counted; it is also more accurate to say that if your condition does not access the resource field, it will not be counted. Bear in mind that even if you accessed resource and your rule succeeded, you'd get only 1 read operation at most as mentioned, not two. It only counts on deny as we've already tested.

(1) This will deny and not count towards your reads:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false && resource.data
    }
  }
}

(2) This will deny but count towards your reads because you accessed resource.

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if resource.data.readable; // always false
    }
  }
}

(1) Resulted in 0 usage with 100 denied requests.
(2) Resulted in 100 usage with 100 denied requests.

Here's a tip to know if you're going to get billed a read operation or not.

In the Rules Playground:

If you see a resource on the right, that means this rule has accessed resource, which means it billed you a read operation.

Such as: First security rule that accesses resource with resource visible on the right And (.readable is false in the document): Second security rule that accesses resource with resource visible on the right

If you don't see resource on the right, that means this rule has not accessed resource, and thus hasn't billed you a read operation.

Such as (resource.data is always true): Third security rule that does not access resource with resource not visible on the right

References:

  1. https://firebase.google.com/docs/rules/rules-language#basic_structure
like image 39
Beyondo Avatar answered Nov 03 '25 20:11

Beyondo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!