SCAN YOUR FIREBASE STUDIO APP FOR VULNERABILITIES

ENTER YOUR FIREBASE STUDIO APP URL

Enter your deployed app URL to check for security vulnerabilities.

Firebase Studio is Google’s Gemini-powered dev environment (derived from Project IDX): you describe the app, the Gemini agent generates a full-stack Firebase app, and it wires the frontend straight into Firebase — Firestore, Authentication, Storage, and Cloud Functions. The IDE is sandboxed, but the output is a normal Firebase app with all the normal Firebase risks.

The thing to understand about a Firebase app is architectural. Unlike a traditional backend, Firebase is directly reachable from the client — the browser talks to Firestore and Storage over the network. That makes Security Rules the real authentication boundary, not code you can hide. A rule that says allow read, write: if true;, or the console’s “test mode” rule that expires to a permanent open state, is a public database. The firebaseConfig in your bundle (API key and project ID) is public by design — it identifies the project, it does not protect it. The only thing standing between your data and the internet is the rules layer.

The Gemini agent generates working reads and writes fast, and “working” during development often means permissive rules that were never tightened. A black-box scan probes the deployed app the way an attacker would — attempting cross-tenant reads, checking whether Storage was locked down along with Firestore, and calling Cloud Functions without auth — to find the boundary the agent left open.

Common vulnerabilities we find in Firebase Studio apps

Open or expired Firestore rules

The Studio default for new projects is “test mode” — an open rule with an expiry date that usually arrives well after launch, at which point the project is either wide open or hard-failing:

// Test mode: public until the timer runs out, then still deployed and forgotten
match /{document=**} {
  allow read, write: if request.time < timestamp.date(2026, 9, 1);
}

The exploit needs no account and no browser. Firestore has a REST API, and the project ID is in your bundle:

curl "https://firestore.googleapis.com/v1/projects/YOUR-PROJECT/databases/(default)/documents/users"

If that returns documents, so does every scraper. The fix is ownership-keyed predicates per collection, deployed with firebase deploy --only firestore:rules:

match /notes/{noteId} {
  allow read: if request.auth != null && request.auth.uid == resource.data.owner_id;
  allow create: if request.auth != null && request.auth.uid == request.resource.data.owner_id;
  allow update, delete: if request.auth != null && request.auth.uid == resource.data.owner_id;
}

See the Firebase safety analysis for the full rule patterns.

Rules that check login but not ownership

The most common non-obvious bug is a rule that authenticates but never authorizes:

// Any signed-in user can read every other user's documents
match /notes/{noteId} {
  allow read: if request.auth != null;
}

Sign in as user B, request user A’s document path, and the rule waves it through — Firestore’s version of BOLA. The create case needs request.resource.data (the incoming document) while reads and deletes need resource.data (the stored one); mixing them up is how “secure-looking” rules still let anyone write a document owned by someone else.

Missing or forgotten Storage rules

Firestore rules and Storage rules are separate files with separate deploys — firebase deploy --only firestore:rules does nothing for Storage. Generators that scaffold Firestore plus image upload routinely lock the database and leave the bucket on the default. Scope by path, and bound size and type while you are there:

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/{allPaths=**} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow write: if request.auth != null && request.auth.uid == userId
                   && request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Without the size predicate, one uploader can drain your quota; without the content-type predicate, your bucket serves whatever they upload from your domain.

Web config vs service credentials

The public firebaseConfig is fine in the bundle. The danger is a service account JSON or an Admin SDK key that ends up in client-reachable code — that credential bypasses every Security Rule, granting full read/write to the whole project. The fix is to keep Admin SDK credentials server-side only (Cloud Functions, Secret Manager) and rotate anything that ever shipped to a public surface. The Token Leak Checker finds service-account keys in the deployed bundle.

Unauthenticated Cloud Functions

Cloud Functions run with Admin SDK privileges and bypass Security Rules entirely, so a function without its own auth check is a complete bypass of everything above. The agent sometimes ships the check as a comment, or authenticates without confirming ownership. Both gates belong at the top of every callable:

exports.deleteNote = onCall(async (request) => {
  if (!request.auth) throw new HttpsError("unauthenticated", "Sign in required.");
  const note = await db.collection("notes").doc(request.data.id).get();
  if (note.data()?.owner_id !== request.auth.uid) {
    throw new HttpsError("permission-denied", "Not your note.");
  }
  await note.ref.delete();
});

HTTP functions get no request.auth at all — you verify the bearer token yourself with admin.auth().verifyIdToken(token) and reject on failure. Test by calling the function URL with no token: anything other than a 401 or 403 is the finding.

App Check not enforced

Everything above assumes requests come from your app. Without App Check they do not have to: the public config is enough to drive Firestore, Storage, and Functions from a script with no browser involved. App Check attests that a request came from your registered app (reCAPTCHA Enterprise on web) and, once enforcement is on per service, rejects everything else. Rules stay the authorization boundary; App Check keeps automated traffic from ever reaching them.

Check it yourself in five minutes

Before running any scanner, three commands tell you whether the rules layer exists at all. Open your deployed app, copy projectId and storageBucket out of the firebaseConfig in the page source, then:

# 1. Can anyone read a collection without signing in?
curl "https://firestore.googleapis.com/v1/projects/PROJECT/databases/(default)/documents/users"

# 2. Is the storage bucket listable by strangers?
curl "https://firebasestorage.googleapis.com/v0/b/PROJECT.appspot.com/o"

# 3. Does a Cloud Function answer with no token?
curl -X POST "https://REGION-PROJECT.cloudfunctions.net/FUNCTION" \
  -H 'Content-Type: application/json' -d '{"data":{}}'

Documents, a file list, or a 200 from the function each mean the boundary is open to anyone who reads your bundle. A PERMISSION_DENIED is the answer you want. What this quick pass cannot tell you is whether signed-in user B can read signed-in user A’s data — that needs two real accounts and every path exercised, which is where the scan takes over.

How VibeEval works with Firebase Studio

  1. Enter your Firebase-hosted app URL. Works with web.app, firebaseapp.com, and custom domains alike — no project access required for the black-box pass.
  2. The agent probes the app in the browser. It reads the public config, attempts cross-tenant Firestore and Storage reads to find rules that check login but not ownership, tests whether Storage was locked down with Firestore, calls Cloud Function endpoints without auth, checks App Check enforcement, and greps the bundle for service-account credentials.
  3. You get a report you can act on. Each finding carries a severity, the request or read that demonstrates it, and paste-ready fix guidance — rule snippets and function-auth changes you can apply and redeploy.

Manual testing vs VibeEval

Dimension Manual review VibeEval scan
Time per full pass Hours reading rules and every function Minutes against the deployed URL
Cross-tenant read coverage Tedious two-account path testing Automated cross-tenant probes
Firestore + Storage parity Easy to lock one, forget the other Both checked every pass
Re-run after each agent edit Rarely happens at dev pace One click, repeatable every deploy
Function-auth / App Check checks Manual endpoint and console review Checked every pass
Rule-logic intent Strong — a human understands intent Not a substitute; scanner flags open reads, not intent

Manual review and the Firebase Emulator are still needed to reason about rule logic — whether a given predicate expresses the access you actually intend. The scanner wins on repeatability: it re-attempts the cross-tenant reads and function-auth checks after every Gemini edit, when hand-testing the rules has long since stopped.

Frequently asked questions

Can VibeEval test my Firestore security rules?

VibeEval performs black-box testing against the deployed app to find rule bypasses — cross-tenant reads, open collections, and Storage rules that were left on the default. For exhaustive per-collection rule probing, the Firebase Scanner exercises every collection directly.

Does Firebase provide enough security by default?

Firebase has excellent infrastructure security, but the rules layer is on you, and the console’s default test mode is deliberately permissive. Default rules are commonly too open, and the “test mode” timer expires to a permanent open state. Never deploy with default rules.

Why is the Firebase config exposed in the browser?

Because it is meant to be — the API key and project ID identify your project, they do not authenticate it. Treating the config as a secret is wasted effort; treating Security Rules as the only barrier between your data and the public internet is the correct mental model.

How do I secure Firebase Cloud Functions?

Validate the auth token before doing any work (context.auth for callables, verifyIdToken for HTTP functions), enforce App Check, and set CORS to your production origin rather than *. Cloud Functions bypass Security Rules, so their own auth check is the only thing protecting them.

Test your Firebase Studio app before launch

Run VibeEval against your Firebase Studio app for the open-rules, ownership-bypass, forgotten-Storage, and unauthenticated-function patterns the Gemini agent most often leaves in. Start testing before you go live.

SCAN YOUR DEPLOYED APP

Paste your live URL. We probe exposed keys, missing auth, open databases, and broken access control — results in under 60 seconds. 14-day trial, no card.

14-day free trial · No credit card · Cancel anytime

START FREE SCAN