42

I recently received an email from firebase telling me that my realtime database has insecure rules. These are the rules that I have set:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
 }
}

Is this not a secure rule?

Email/Password is the only sign-in method that I have enabled.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
F0r3v3r-A-N00b
  • 2,903
  • 4
  • 26
  • 36
  • It's may be because you're allowing access to all the data when the user logged in. You should only allow the logged user and common data but not all data. – MuruGan Jul 18 '18 at 02:03
  • you have to specify tree level rules also. – MuruGan Jul 18 '18 at 02:05
  • those rules seem fine, did you checked that the email is from that project? – Gastón Saillén Jul 18 '18 at 02:18
  • @MuruGan I only have one tree and all users, as long as they are authenticated, are allowed to read and write to this tree. That's why my rules are written that way. – F0r3v3r-A-N00b Jul 18 '18 at 02:27
  • @GastónSaillén Yes I checked that the email pertains to my project. – F0r3v3r-A-N00b Jul 18 '18 at 02:31
  • 1
    Recently firebase team found that, so many projects have security issues following that why they sent you the mail. Try to contact firebase support team for further details – MuruGan Jul 18 '18 at 02:34

3 Answers3

76

firebaser here

I'm sorry if the email wasn't very explicit about what isn't secure about those rules. Securing your user's data is a crucial step for any app that you make available, so I'll try to explain a bit more about how that works below.

The (default) rules you have allow anyone who is signed in to your back-end full read/write access to the entire database. This is only a very basic layer of security.

On the one hand this is more secure than just granting everyone access to your database, at least they have to be signed in.

On the other hand, if you enable any auth provider in Firebase Authentication, anyone can sign in to your back-end, even without using your app. Depending on the provider, this can be as easy as running a bit of JavaScript in your browser's developer console. And once they are signed in, they can read and write anything in your database. This means they can delete all data with a simple command like firebase.database().ref().delete().

To make the data access more secure, you'll want to more tightly control what each signed-in user can do. For example, say that you keep a profile with information about each user under /users. You might want to allow all users to access these profiles, but you definitely want users to only be allowed to modify their own data. You can secure this with these rules:

{
  "rules": {
    "users": {
      ".read": true,
      "$user_id": {
        // grants write access to the owner of this user account
        // whose uid must exactly match the key ($user_id)
        ".write": "$user_id === auth.uid"
      }
    }
  }
}

With these rules, everyone (even non-authenticated users) can read all profiles. But each profile can only be modified by the user whose profile it is. For more on this, see the Firebase documentation on securing user data.

In addition to ensuring that all access to data is authorized, you'll also want to ensure that all data stored is valid to whatever rules you have for you app. For example, say that you want to store two properties for a user: their name, and their age (just for the sake of the example, in reality you'd probably store their date-of-birth instead). So you could store this as something like:

"users": {
  "uidOfPuf": {
    "name": "Frank van Puffelen",
    "age": 48
  }
}

To ensure only this data can be written, you can use this rules:

{
  "rules": {
    "users": {
      ".read": true,
      "$user_id": {
        ".write": "$user_id === auth.uid",
        ".validate": "data.hasChildren(['name', 'age'])",
        "name": {
          ".validate": "data.isString()",
        },
        "age": {
          ".validate": "data.isNumber()",
        },
        "$other": {
          ".validate": false
        }
      }
    }
  }
}

These rules ensure that each user profile has a name and age property with a string and numeric value respectively. If someone tries to write any additional properties, the write is rejected.

Above is a quick primer on how to think about securing your (user's) data. I recommend that you check out the Firebase security documentation (and the embedded video) for more.


Update: since May 2021 you can also use Firebase App Check to restrict access to calls just coming from your web site or app. This is another, quick way to reduce the abuse of your database. This approach is not foolproof though, so you'll want to combine App Check for broad protected, with the security rules for fine-grained control.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 21
    We have `{"rules":{".read":"auth != null"}}` because we have no private per-user data, only public data. But we get emails for weeks now saying "any logged-in user can read your entire database" – Jonny Aug 25 '18 at 03:25
  • 6
    Hey Jonny. If your rules intentionally allow public reading of all data, you don't store user data, and you're willing to pay the charges for folks reading all data, then your rules fit your intended usage. In that case the email is indeed overly noisy. There is currently no way to disable them, as we want to ensure developers are aware of the potential risk that their rules expose their users to. You might want to [file a feature request](https://firebase.google.com/support/contact/bugs-features/) to allow disabling the email, although I expect it's a bit too soon for adding that option. – Frank van Puffelen Aug 25 '18 at 14:29
  • 1
    Thanks. The read rule is for all data in the database. We have three top "folders" - would it help to remove the global read rule, and specify the same read rule for each of the three folders? I guess that even if I tried, I wouldn't know until after a few weeks if the emails will stop because I assume there is no way to test that adhoc (?). – Jonny Aug 25 '18 at 16:17
  • I indeed don't think there's a way to test. I could look up the check that the back-end does for sending that email, but I know there have already been changes to it, so there's no guarantee they won't change again. If you want help securing your data, your best bet is to open a new question with an [MCVE](http://stackoverflow.com/help/mcve). – Frank van Puffelen Aug 25 '18 at 16:29
  • So, after a few weeks of testing my narrowed rules on two separate but exact copies of the production environment I have come to two conclusions: 1. I was right. (Don't define global rules, define rules as deep in the structure as possible) 2. The emails come in on a weekly interval. – Jonny Sep 09 '18 at 00:15
  • 3
    @Jonny and to anyone else here, FINALLY there's a toggle under Alerts, that you can use to opt out from these emails. – Lord Zsolt Feb 02 '21 at 10:55
  • How to test my rules are satisfactory? I respond to these mails and edit the rules but now I get a 1 day notice! I use this db regularly (although the mail says 'unused'). It contains vital information for me. – majodi Jun 02 '21 at 08:46
  • Hey @majodi. If that email is indeed about a database that is actively being used, that seems unexpected. You might want to [reach out to Firebase support](https://firebase.google.com/support/contact/troubleshooting/) for personalized help in troubleshooting, as we can't check the database or reason for the email from here. – Frank van Puffelen Jun 02 '21 at 14:04
  • 1
    @FrankvanPuffelen I'm sorry, my bad. Turned out they were talking about the "Realtime" db only. I bet there are more people like me reading over that. But again, my bad. – majodi Jun 03 '21 at 16:55
11

You can also mute alerts by visiting the link at the bottom of the email.

https://console.firebase.google.com/subscriptions/project/<YOUR_PROJECT_NAME>

enter image description here

HimalayanCoder
  • 9,630
  • 6
  • 59
  • 60
-1

I changed rules

{
  "rules": {
    "users": {
      ".read": true,
      "$user_id": {
        // grants write access to the owner of this user account
        // whose uid must exactly match the key ($user_id)
        ".write": "$user_id === auth.uid"
      }
    }
  }
}

But after that page not working.