Is Firebase’s Firestore database secure?

7 min readDec 9, 2021

Updated 23 Jan 2023 — review, updated screenshots

Firestore is Firebase’s most recent form of database engine. It’s real-time, quick to integrate into Android, iOS and web apps, and very easy for a novice developer to learn. Data is written in documents which are contained in collections, and Firebase supports a near-unlimited number of both.

And for the most part, as a standalone unit, it’s extremely secure. We’ve carefully analysed different potential hacks against Firestore’s core APIs and engines, and found nothing which should preclude its use in very secure situations or for particularly sensitive data.

But, like any database engine, Firestore is only as secure as the developer has set it up to be. Firestore’s data security is built on a system of programmable rules which define which kinds of user can access which pieces of data. For example, you can say that a user can access everything stored under his ID, but nothing under anyone else’s.

Whilst those rules are (to the best of our testing) impossible to circumvent, they are as prone to programming and process mistakes as any other part of the software. And they can be quite complicated to get right.

In short, any technology is insecure when developers screw up, but Firebase is perhaps easier to screw up than others.

So here is a list of security issues in Firestore and how to work around them:

Firestore isn’t secure out-of-the-box

(…Or if it is, it’s unusable.)

When you create a Firestore database you get a choice of security modes:

Screenshot of the Firestore security mode dialog
The Firestore security mode dialog

That’s a choice between everything being open, or nothing working. It’s very black-and-white.

Bearing in mind that the service is sold on its easy learning curve, novices reading the options will no doubt choose the “testing” option (everything is open).

That option does of course time out after 30 days. But the danger is that within those 30 days of complete openness, developers will have been able to design some of their data structures and write some of their code. In other words it pushes novice developers to write first and consider security second. This is enormously problematic since in Firebase, perhaps more than any other kind of database, security is reliant on the layout of those data structures. More on that to follow.

But the upshot of all that is that often when security does get a look-in, it’s already too late. The data has likely been architected in such a way that it can’t be secured. It’s easy, therefore, to take shortcuts and deliver a product with significant security holes.

This isn’t just hypothetical, it’s something I’ve seen time and time again in applications I’ve audited.

The solution is to do things in the opposite order to how Google guides you. You must consider security first and then architect your data to suit it.

Firestore’s security rules are error-prone

Firestore doesn’t have an API layer like most databases. This is key to its flexibility and ease-of-use, and one of the big reasons people like me use it.

Consider this very common way of architecting an app’s back end:

Diagram showing traditional client/API/database architecture
Traditional client / API / database architecture. The client has no direct access to the database.

Here the database is just for storing data deep within the back end. Clients didn’t interact with it directly at all; in fact good security practice is to prevent it from being directly internet accessible at all. Instead clients call a single-use API method — say, “update my user profile”, and the API server performs a fixed action on the database to carry out that task.

With Firebase there is no API. You act directly upon the database, and your actions are governed by the rules system described above.

This architecture has benefits and disadvantages, and there are plenty of people with passionate views either way. The reality is that both are prone to security flaws caused by fallible humans, in the form of architecture and process errors.

Firebase’s particular problem in this arena is that rules often need to be crazy complex. For example, whilst it’s fairly easy to lock down a collection of data to a single user, it can be very complex to open that same collection up to a group of people.

Whilst Firestore’s security rules langage is a topic for a future blog, the one thing that’s absolutely critical is to build unit tests for those rules. It’s a brilliant opportunity to try out your team’s Test Driven Development skills.

Solution: always unit test your rules.

Firestore rules rely on Firebase Auth, which isn’t always secure

Any secured resource is only as secure as the authentication system which lets people in through the door.

In Firestore’s case, that system is Firebase Auth. Firestore’s rules rely heavily on user authentication data and tokens provided by Auth.

Firebase Auth has a sometimes worrying relationship with security. In short, it needs to be navigated carefully because many of its features and modes of operation are simply insecure.

Solution: Make sure you have set up Auth in a secure way before addressing Firestore.

You’re stuck with a chosen geographic data location

Screenshot of database region dialog in Firestore
The Firestore region choice dialog

Generally, a company’s data policies will place restrictions on where in the world data can be stored.

Firestore allows you to select a world region. One enormous potential problem is that this region can’t be changed once set, so ensure that your developers know what it should be at the time they start building the project.

Security rules can’t apply to individual fields, only whole documents

This means some combinations of data are impossible to secure correctly. This is a problem which we see all the time, with varying degrees of subtlety. Here’s a particularly unsubtle example.

Imagine you have a user document that has this layout:

Screenshot of poorly considered database layout, in which the user’s name, phone number and isAdmin property are all stored in the same collection

The user’s information is stored here: their name and phone number. Obviously the user needs to update this information from time to time, so it’s right to make it writable by them.

But this document also contains security information about that user, because it contains the isAdmin field.

The problem is that by making the user’s document writable by the user, the user will also get to decide whether or not they are an administrator!

There are several solutions to this. The one we use, which fits the security need as well as maintaining efficiency and scalability, is to have a totally separate collection containing documents with users’ security information.

So for example the above layout could be changed to this:

The User document no longer has an isAdmin property
The ‘Users’ collection contains information that the user can edit themselves…
Database screenshot showing the isAdmin property having moved to a separate document in the UserSecurityInfo collection
…And the ‘UserSecurityInfo’ contains security-sensitive data which they can’t.

Here there is a separate collection (UserSecurityInfo) containing only information about users which they can’t themselves edit. The security rules can then be set differently for each collection.

Firebase Functions triggers can’t be used for security purposes

A particularly great feature of Firestore is that the database can itself respond to changes in the data it holds.

This is done using Firebase Functions triggers. The triggers are rules along the lines of, “when a user edits document X, run function Y.”

It’s tempting to use this for security purposes, for example to verify what the user writes to the database and to revert any writes if needed. But that is not a secure solution, because the data has already hit the database by the time that the function runs.

So if the user writes something they shouldn’t, it will have already been made live, however briefly. This gives a bad guy a window of opportunity.

It doesn’t cache its data securely at rest

On Android at least, Firestore doesn’t follow Google’s own security recommendations in that its local cache is not properly secured. Data from the Firestore database is stored on the client phone/tablet with no encryption whatsoever. This renders it incompatible with OWASP rule MSTG-STORAGE-1, and is therefore in breach of many organisations’ data policies.

Here is my blog with the original research on this point.

In conclusion

Firestore is a great, easy-to-use, flexible and scalable database with many great features. When used correctly, it’s perfectly secure (to the best of our research).

But it’s potentially difficult to secure correctly, and that is its weakness. It’s a service targeted either at complete novices, or presented to developers as easy-to-learn. This is at least in part why we see so many poorly secured Firestore databases.

That said, Firestore is a great choice of back end so long as you take the time to fully and completely learn how its security rules work.

--

--

Tom Colvin
Tom Colvin

Written by Tom Colvin

Android developer / consultant; freelancer or through my agency Apptaura. Google Developer Expert in Android. tomcolvin.co.uk Articles 100% me, no AI.

Responses (1)