On Monday morning I got a message from a colleague in the security department. Since the previous day, $44,000 had been spent on the Gemini AI API. My first thought was immediate, visceral dread — on Friday I had set up a Claude Code-powered vibecoding environment for managers and designers, and my brain went straight to “what have they done over the weekend?” I started mentally drafting the post-mortem before I even opened the billing dashboard.
It wasn’t the AI setup. A quick investigation revealed the actual source: the company’s Android app had a Google Cloud API key originally provisioned for Firebase and Google Maps. That key had all APIs enabled. And because it was embedded in the APK, it was available to anyone willing to spend five minutes with a decompiler. Someone had found it and pointed it at Gemini.
The relief that my Friday deployment wasn’t the cause lasted about three seconds before the severity of the actual problem set in.
What Was in the APK
An APK is a ZIP archive. Inside it sits compiled Dalvik bytecode, resources, assets, and configuration files — including things like google-services.json, where Firebase stores its API key. The key is right there in plaintext, and it has to be, because the Firebase SDK reads it at runtime.
Google has always been clear that Firebase API keys are identifiers, not secrets. They are safe to embed in client apps because Firebase Security Rules and IAM permissions are what actually control access. The key itself is just an address. This is true, and it is also dangerously incomplete, because the security of that key depends entirely on what APIs it is authorized to call.
When you create an API key in the Google Cloud Console without configuring restrictions, it can call every API enabled on the project. Firebase, Maps, Translate, Vision, and — as of relatively recently — Gemini and the rest of the Vertex AI family. A key that was perfectly safe when it only had access to Firebase Authentication and Maps SDK suddenly becomes a blank check on your cloud account the moment someone enables a generative AI service on the same project.
The extraction is trivial. JADX decompiles DEX bytecode back into readable Java source. APKLeaks automates scanning for hardcoded secrets. You do not even need sophisticated tooling — running strings against the unzipped APK contents and grepping for AIza (the prefix of every Google API key) will find it in seconds. Every Android developer knows this. The problem is not that the key is in the APK. The problem is that the key can do things it was never intended to do.
Forty-Three Minutes
The incident response is the part of this story I am genuinely proud of. Corporate incident response procedures worked exactly as designed. Within minutes of the initial alert, a dedicated incident channel was formed. The relevant managers, developers, and stakeholders were on it almost immediately — security, platform engineering, the mobile team lead, and the finance stakeholders who needed to understand the billing impact.
The first action was not to rebuild the app or rotate the key. It was to restrict the API key’s permissions in the Google Cloud Console, limiting it to only the APIs the app actually uses: Firebase and Maps. This is a server-side change. It takes effect immediately, without deploying a new version of the app, without waiting for app store review, without any action from end users. This architectural property of GCP’s key restriction system — that permissions are enforced at the API gateway, not in the client — is what made the 43-minute response time possible.
Forty-three minutes after I received the initial message, our monitoring metrics showed that the unauthorized traffic was dropping. The incident was marked as mitigated. The total elapsed time from “something is wrong” to “the bleeding has stopped” was under an hour, and the actual fix — restricting the key — took a fraction of that.
One operational detail worth noting: we confirmed mitigation through API monitoring metrics, not through the billing dashboard. GCP billing data can lag four to twelve hours behind actual usage. If we had waited for the billing numbers to drop, we would have spent hours wondering whether the fix worked. Cloud Monitoring metrics on API request counts update within minutes, and that is what we used to verify that the restriction was effective.
Work on properly fixing the app — rotating the key, implementing per-API keys with application restrictions, and adding Firebase App Check — began when the mobile team started their day a couple of hours later.
Why AI APIs Changed the Risk Calculus
Exposed API keys in mobile apps are not a new problem. The security community has been writing about this since 2015. But for most of that decade, the financial exposure was bounded. A leaked Maps API key might generate a few thousand dollars in geocoding abuse before someone noticed. A leaked Firebase key with only Firebase APIs enabled was essentially harmless. The risk existed, but the blast radius was manageable.
Generative AI APIs changed the math overnight. Services like Gemini, GPT-5, and Claude charge per token at rates that can scale to tens of thousands of dollars per day under sustained automated use. The same exposed key that might have cost $500 per month in Maps abuse can now cost $44,000 in a single day when someone routes Gemini requests through it. Other organizations have reported worse: $82,000 in 48 hours from a key exposed in a public GitHub repository, over $450,000 in 45 days from a compromised service account key.
The economics of API key exposure shifted before the security practices caught up. Keys that were provisioned years ago, when the worst-case scenario was moderate Maps or Translation API abuse, now grant access to AI services that did not exist when those keys were created. Nobody went back to add restrictions because nobody re-evaluated the risk. The key was “fine” — until it wasn’t.
Restricting Keys Before They Leave Your Build
Prevention is a layered problem, but the layers are not equally important. Here is how I would prioritize them, starting with the highest-impact change.
Restrict the key’s API access. This is the single most effective mitigation and it takes five minutes. In the Google Cloud Console, go to your API key’s settings and switch from “Don’t restrict key” to a specific list of allowed APIs. If the key is used for Firebase and Maps, restrict it to exactly those APIs. If someone extracts it from your APK, they get Firebase and Maps access — which is the intended design — and nothing else. No Gemini, no Vertex AI, no Translation API. Do this first. Do this today.
Add application restrictions. Configure the key to only accept requests from your Android app by specifying your package name and SHA-1 signing certificate fingerprint. This makes the key significantly harder to abuse even for the APIs it is allowed to call, because requests from other apps or scripts will be rejected. It is not bulletproof — the X-Android-Package and X-Android-Cert headers can theoretically be spoofed — but it raises the bar substantially.
Use per-purpose keys. Rather than one key shared across Firebase, Maps, and whatever else gets added later, create separate API keys for each service, each with its own restrictions. When a key is compromised, the blast radius is limited to one service rather than everything on the project.
Set budget alerts at aggressive thresholds. GCP budget alerts are free to configure and can trigger on actual or forecasted spend. Set them at levels that would indicate abuse, not just levels that indicate normal growth. A $1,000/day alert on a project that normally spends $50/day would have caught this incident hours earlier.
Implement Firebase App Check. App Check verifies that incoming requests originate from a legitimate instance of your app, not from a script using an extracted key. It adds meaningful protection but is not a substitute for key restrictions — treat it as a defense-in-depth layer, not a primary control.
The Key You Forgot About
The most dangerous API keys in your organization are not the ones you provisioned last week with careful restrictions and per-API scoping. They are the ones someone created three years ago for a prototype. They have all APIs enabled because that was the default. They have no application restrictions because nobody configured them. They are sitting in APKs that have been through dozens of release cycles, in Docker images on registries nobody monitors, in CI/CD environment variables that predate your current security practices.
Every one of those keys is now a potential five-figure liability, not because anything about the key changed, but because the APIs available on the project changed. The fix is not complex — GCP key restrictions take minutes to configure. But it requires someone to audit the keys that already exist, not just the ones being created today.
Open your Google Cloud Console. Go to APIs & Services, then Credentials. Sort your API keys by creation date. Check the restrictions on the oldest ones. The one that worries you most is probably the one nobody remembers creating.