, , ,

Aug 15, 2025 | 4 Minute Read

How Client-Side Access Can Jeopardize Your App And How to Secure It

Sonesh Tandel, Senior Software Engineer

Table of Contents

Introduction

The rise of Firebase has revolutionized how developers approach rapid application development. With its serverless architecture, real-time data synchronization, and seamless integration with frontend apps, Firebase has become a go-to choice for startups and enterprise teams looking to launch fast. But in the pursuit of speed, many teams fall into a hidden trap: unintentionally exposing their entire data layer to the client.

What starts as a lean, agile stack can quickly become a ticking time bomb if access rules aren’t correctly implemented. While Firebase simplifies backend infrastructure, it demands maturity in how developers manage data access and enforce security. Unlike traditional architectures where API layers naturally gate access, Firebase puts the onus of access control directly on the Firestore security rules.

In this blog, we dive into a real-world scenario where an engineering team inherited a Firebase-powered application. With launch deadlines looming and no time for backend re-architecture, they were forced to secure a dangerously open Firestore setup, without breaking functionality or user flow.

The Tradeoff: Speed Vs. Security

The development team found themselves in a high-pressure environment: the client had already built the foundation of the mobile app using Firebase and was pushing hard to go live quickly. There was no room to re-architect the backend without missing critical deadlines.

While Firebase's speed made it a natural fit for MVP-style timelines, it came at the cost of architecture-level control. Firestore was being accessed directly from the mobile client, and the backend logic was being handled by Firebase Functions. This meant any authenticated user had access to the raw database, with little to no access control in place.

Speed was achieved, but security was compromised.

The Hidden Vulnerability In Application Implementation

Firestore, by design, allows frontend apps to interact directly with the database. This simplicity is part of Firebase’s appeal, but it also opens up a host of security vulnerabilities if not configured carefully.

In the inherited system, several risks were uncovered:

  • Unrestricted Access: Users could read from or write to collections they had no business touching.
  • Impersonation Threats: A malicious user could spoof another user's identity and create or modify records in their name.
  • Data Leaks: Sensitive information could be viewed by unintended users.
  • Accidental Deletions: No safeguards were in place to prevent unintentional or malicious data deletions.

The database was effectively open. This isn’t just a poor practice; it’s a severe data breach risk that could lead to real consequences, especially in regulated or user-sensitive environments.

The Security Fix: Locking Down The Database With Firestore Rules

With no option to build a traditional backend, the team had to secure the existing setup using Firestore’s native capabilities. That meant implementing security rules,  line by line, collection by collection.

The first step was a complete audit:

  • Which collections were being accessed by the client?
  • Which ones were read-only vs. write-enabled?
  • Were any collections used exclusively by backend functions?

Security strategy included:

  • Blocking client-side access entirely for sensitive collections which contained in-app purchase records accessed only through backend APIs.
  • Allowing limited access to certain collections, where users could create records but only administrators could view or modify them.
  • Restricting collections to read-only on the client, while managing updates directly in Firebase Console.
  • Completely locking down logging-related collections such as prompts and brightdata since they had no role in business logic.

Rules were tested iteratively. After locking down one collection, the team would verify if the app still functioned correctly. Only after confirming stability would they move to the next collection.

This step-by-step approach ensured that no critical features broke unexpectedly, and every rule had a functional validation path. 

The Technical Challenge: Writing Secure Rules At Scale

Firestore security rules are declarative, scoped, and hierarchical. Unlike traditional backend code, they don’t follow a standard programming paradigm, which creates a steep learning curve.

Challenges faced included:

  • Navigating nested collection structures
  • Writing conditional logic for user-based access
  • Implementing custom checks using request.auth.uid against document ownership
  • Preventing privilege escalation
  • Ensuring rules are not overly permissive

One key insight was that minimal access wins. The team started from a "deny all" posture and gradually opened access based on strict criteria:

  • Is the user authenticated?
  • Are they the owner of the document?
  • Should they have read-only, write-only, or full access?

In many cases, rules resembled:

 

Over time, the team developed a set of reusable rule patterns that helped them lock down access consistently across all collections.

Why Not Build A Custom Backend?

A traditional backend would have introduced a REST or GraphQL API layer to control all database interactions. This would naturally separate concerns, enforce access control at the API level, and remove the client-side database exposure entirely.

However, this approach wasn’t practical under the circumstances:

  • The backend build would require weeks of additional development.
  • The client’s business priorities emphasized time-to-market.

Instead, the team chose a pragmatic route: work within Firebase's architecture but harden it with precision.

This decision ultimately allowed the project to meet its delivery goals while significantly improving its security posture.

Key Takeaways For Engineering Teams

Here are the essential practices and mindsets that helped the team secure the platform without a full rebuild:

  1. Do not launch Firebase apps without security rules. Even MVPs need protection.
  2. Audit inherited Firebase projects thoroughly. What you don't know can hurt you.
  3. Approach security incrementally. One collection at a time with end-to-end testing.
  4. Use clear patterns. Leverage rule structures that can be reused across collections.
  5. Educate your developers. Firestore rules are not intuitive and require dedicated attention.
  6. Know your tradeoffs. Firebase offers speed, but securing it requires maturity.

A Cautionary Tale With A Secure Ending

Firebase offers incredible benefits: rapid prototyping, managed infrastructure, and deep integration between database, functions, and hosting. But the same features that make Firebase attractive can also lead to security pitfalls when misunderstood or misapplied.

In this case, a fast-moving team inherited a vulnerable architecture and turned it around through diligent rule-writing, testing, and a solid understanding of Firestore’s mechanics. They didn’t rebuild the system; they secured it.

If you're launching with Firebase or picking up a project that uses it, make security rules your first task, not your last. It's not just about protecting data, it's about protecting your users, your product, and your trust. Want to discuss more? Let's talk.

 

About the Author
Bassam Ismail, Director of Digital Engineering

Bassam Ismail, Director of Digital Engineering

Away from work, he likes cooking with his wife, reading comic strips, or playing around with programming languages for fun.


Screenshot 2025-08-18 at 9.00.39 PM

Sonesh Tandel, Senior Software Engineer

Curious by nature, Sonesh is passionate about Cricket, Harmonium, and all things Marvel. He’s also a quick learner and problem solver. His core life values? Truthfulness, forgiveness, growth, and selflessness.

Leave us a comment

Back to Top