TL;DR
- Risk level: High
- Who is affected: Any developer who followed Google’s official guidance to embed
AIza...API keys in public HTML or JavaScript - Main issue: Keys created for Google Maps, Firebase, and other “public” services silently gained access to Gemini when the Gemini API was enabled on the same project
- Scale: 2,863 live exposed keys found in a single November 2025 web crawl dataset—including keys on Google’s own infrastructure
- Attack cost: Near-zero. Attacker scrapes your page source, copies the key, and calls the Gemini API
- Damage: Private file access, AI bill fraud (~$1,000s/day), quota exhaustion
What the platform does
Google Cloud uses a single API key format—strings beginning with AIza—for two fundamentally different purposes:
| Use | Intended sensitivity | Official guidance |
|---|---|---|
| Google Maps embed | Public | Paste directly into HTML |
| Firebase project identifier | Public | Safe to expose in client code |
| Gemini API authentication | Secret | Requires restricted, private key |
The problem: Google uses the same key format and the same key objects for all three.
Google’s own Firebase security checklist explicitly stated: “API keys are not secrets.” Google Maps documentation instructed developers to paste keys directly into their HTML. This was correct advice—for a decade.
Then Gemini arrived.
The actual risk
Retroactive privilege escalation
When a developer enables the Gemini API (generativelanguage.googleapis.com) on a Google Cloud project, every existing unrestricted API key in that project immediately gains access to Gemini endpoints. No warning is shown. No confirmation is required. No email notification is sent.
The sequence:
- Developer creates an API key in 2022 for Google Maps and embeds it in public JavaScript, exactly as Google instructed
- In 2025, someone on the team enables the Gemini API for an internal prototype
- That 2022 Maps key—sitting in public source code on thousands of cached pages—is now a live Gemini credential
- The developer is never told
This is not a misconfiguration by the developer. It is a privilege change applied retroactively to a key that was correctly deployed in a public context.
Insecure defaults
New API keys created in Google Cloud Console default to “Unrestricted”—valid for every API enabled in the project, including Gemini. A developer creating a key for a map widget is silently generating a credential capable of accessing sensitive AI endpoints.
The UI shows a warning about “unauthorized use.” The architectural default remains wide open.
What an attacker can do
The attack is trivial and requires no special tooling:
| |
From a valid key, an attacker can:
- Read private Gemini files —
/v1beta/files/returns uploaded datasets, documents, cached context. Anything the project stored through the Gemini API is accessible without any further authentication. - Read cached content —
/v1beta/cachedContents/exposes context window caches, which can contain sensitive business data. - Run up your bill — Gemini API calls are not free. Depending on model and context window size, maxing out API calls against a single victim account can generate thousands of dollars in charges per day.
- Exhaust your quotas — This can fully shut down legitimate Gemini services for the victim.
The attacker never touches your infrastructure. They interact only with Google’s API using a credential you published to the internet.
Scale of exposure
Truffle Security scanned the November 2025 Common Crawl dataset—a ~700 TiB archive of publicly scraped web content—and found 2,863 live Google API keys vulnerable to this vector.
These were not fringe developer side projects:
- Major financial institutions
- Security companies (the irony is notable)
- Global recruiting firms
- Google’s own infrastructure — Multiple keys on Google product websites, deployed since at least February 2023, that had silently become Gemini credentials
Truffle Security tested one of Google’s own keys against the Gemini /models endpoint (confirmed in-scope by Google) and received a 200 OK.
Disclosure timeline
| Date | Event |
|---|---|
| Nov 21, 2025 | Truffle Security submits report to Google VDP |
| Nov 25, 2025 | Google initially classifies behavior as intended |
| Dec 1, 2025 | After seeing their own infrastructure cited as evidence, Google reconsiders |
| Dec 2, 2025 | Reclassified from “Customer Issue” to “Bug”; severity upgraded; product team engaged |
| Dec 12, 2025 | Google shares remediation plan: internal pipeline to discover and restrict exposed keys |
| Feb 2026 | Truffle Security publishes findings publicly |
The initial “intended behavior” classification is significant. It means Google’s first instinct was that developers simply should have restricted their keys—placing the burden entirely on the developer despite a decade of guidance that these keys were safe to publish.
Evidence quality
| Claim | Confidence | Basis |
|---|---|---|
| 2,863 live vulnerable keys in Nov 2025 Common Crawl | High | Published research; methodology described |
| Google keys on Google’s own infrastructure | High | Truffle Security provided examples to Google during disclosure; Google confirmed |
| Gemini access from unrestricted Maps keys | High | Demonstrated via /models endpoint; Google reclassified as bug |
| $1,000s/day billing impact potential | Medium | Directional; depends on model, context, and rate limits |
Scale of private data exposure in /files/ | Medium | Endpoint structure confirmed; actual victim data contents not published |
Why this is a platform problem, not a developer mistake
Google’s security checklist told developers: API keys are not secrets. Firebase documentation is unambiguous. Maps embeds are copy-paste with the key in plain HTML.
The CWE classifications are accurate:
- CWE-1188: Insecure Default — New keys default to unrestricted access, including Gemini
- CWE-269: Incorrect Privilege Assignment — Existing keys received elevated privileges retroactively without consent or notification
Secure API design separates key types by sensitivity:
| Provider | Approach |
|---|---|
| Stripe | pk_live_... (publishable) vs sk_live_... (secret) — different prefixes, different capabilities |
| Twilio | Separate Account SID vs Auth Token, distinct scopes |
| Google (post-Gemini) | Single AIza... format for both public Maps embeds and private Gemini credentials |
The Stripe model makes a developer mistake difficult by design. The Google model made it invisible.
Mitigations
Regardless of how you got here, the remediation steps are the same:
Immediate audit
- Find every
AIza...key in your codebase and version history —git log -S 'AIza'will search commit history - Check which projects have Gemini enabled — Google Cloud Console > APIs & Services > Enabled APIs
- Test exposure — For any key you find in public code, hit
https://generativelanguage.googleapis.com/v1beta/models?key=YOUR_KEY. A200 OKmeans you’re exposed.
Rotate exposed keys
If a key has ever been committed to a public repository, embedded in public HTML, or shipped in a public JavaScript bundle, treat it as compromised. Rotate it:
- Google Cloud Console > APIs & Services > Credentials
- Create a new restricted key
- Delete the old key
Restrict new keys
Every API key should be restricted to the specific API it needs. In Google Cloud Console:
- Set Application restrictions (HTTP referrer, IP ranges, or Android/iOS app)
- Set API restrictions — select only the specific API (e.g., Maps JavaScript API only)
A Maps key should not be able to call Gemini. Enforce this at creation, not after the fact.
Separate keys per purpose
Never reuse a Maps or Firebase key for Gemini work. Create dedicated, restricted keys for each use case. This is standard practice that Google’s own tooling has historically made easy to ignore.
AIHackers verdict
This is a policy documentation failure at vendor scale. Google told millions of developers that these keys were safe to publish. That advice was correct until it wasn’t—and the change happened silently, retroactively, without notification.
The developer who embedded a Maps key in 2022 followed the rules. The platform changed under them.
If you have Google API keys in any public-facing code: audit now. Test each key against the Gemini endpoint. Rotate anything that shows 200 OK. Restrict every future key at creation time.
If you’re building on Google Cloud: never create an unrestricted key. Apply API restrictions as the first step, not an afterthought.
The 2,863 keys found in a single crawl are the ones Truffle Security looked for. The actual number of exposed keys is almost certainly higher.
What to Do Next
Have Maps or Firebase keys in public code? Run the audit steps above before doing anything else.
Already using Gemini API keys for custom tooling? Verify they are newly created, restricted keys—not legacy Maps/Firebase keys. See guidance in Google Antigravity OAuth Risk for the broader key management picture.
Evaluating Google Cloud for AI workloads? Review the Antigravity OAuth enforcement risk alongside this one—they represent two different ways Google’s access model can fail you without warning.
Related links
- /risks/google/antigravity-oauth-risk/ — Google’s OAuth enforcement crackdown (connects to key management strategy)
- /risks/anthropic/third-party-access/ — How other providers handle access control failures
- /risks/risk-rubric/ — How AIHackers evaluates risk levels
- /verify/methodology/ — Evidence standards used in this analysis
Sources
- Truffle Security: Google API Keys Weren’t Secrets. But then Gemini Changed the Rules. — Primary research; full disclosure timeline and technical breakdown
- Firebase Security Checklist: API keys are not secrets — Google’s own documentation used as evidence against the “developer error” framing
- Google Maps API key setup documentation — Official instruction to embed keys in HTML
- CWE-1188: Insecure Default — Insecure initialization classification
- CWE-269: Incorrect Privilege Assignment — Privilege escalation classification