[Urgent] ~$2200 in unauthorized Gemini API charges from leaked client-side key — requesting refund

TL;DR: My Gemini API key leaked through a Vite-built client JS bundle. An automated scanner extracted it and burned ~$2,200 in API calls directly against generativelanguage.googleapis.com in a single-day burst on April 20–22. Zero traffic touched my own app or user base. Key has been revoked, billing card removed. Hoping Google can credit the unauthorized usage.


Hey all,

I’m posting here in parallel with a billing support ticket because I’ve seen a few recent threads with the same pattern and Google staff have been helpful in resolving them. Sharing the full picture in case it helps anyone else spot this before it happens to them.

What happened

I run a small personal app (content creation tool for video creators — small user base, near-zero baseline Gemini usage). On April 21, I noticed an unexpected ~$2200 charge on my Google Cloud billing. Investigation showed a single-day burst of Gemini API activity completely inconsistent with my actual usage.

Evidence this was third-party abuse, not me or my users

I triangulated three data sources and they all agree:

1. Gemini API dashboard

  • ~100,000 successful requests in a single-day burst (baseline: near-zero for the prior 30+ days)

  • ~300M input tokens during the burst

  • ~1.25M 400 BadRequest errors alongside the successes — a 12:1 fail-to-success ratio

That error pattern is the smoking gun. A human user doesn’t fuzz request formats 12 times for every successful call. That’s an automated script trying different payloads until it finds a working schema.

2. Supabase Auth (my app’s auth provider)

  • Zero new user signups in the 7-day window around the incident

  • No authenticated user could have generated this traffic

3. Railway (where my app is hosted)

  • Flat baseline HTTP traffic throughout the entire incident window

  • Traffic did NOT go through my server — attacker called Gemini directly

Conclusion: someone extracted my key from the JS bundle, ran a script against the Gemini endpoint from their own infrastructure, and billed it all to me.

How the key leaked

Classic Vite footgun. My app used VITE_GEMINI_API_KEY as a shared fallback for users who hadn’t configured their own key. The VITE_ prefix causes Vite to inline the value into the JS bundle at build time — it’s literally a plaintext string in the deployed index-*.js asset. Anyone who loaded the app could extract it with DevTools in 10 seconds.

There are automated scanners that crawl Railway, Vercel, and Netlify subdomains, download JS bundles, grep for AIza-prefixed strings, and test them against the Gemini API. I’m fairly sure that’s how this happened — no one from my user base was involved.

What I’ve done

  • Revoked the compromised API key in AI Studio

  • Removed the payment method from the Cloud billing account (so even if something else leaks, charges can’t accumulate)

  • Taken the app offline (returning 503 from all routes)

  • Started rebuilding with a secure architecture:

    • Gemini key server-side only (no VITE_ prefix, never in the bundle)

    • Supabase JWT auth middleware on all API routes

    • express-rate-limit per-user and per-IP

    • Per-user daily token budgets

My request

Hoping Google can review and credit the ~$2,200 in unauthorized charges. I’ll be submitting the formal billing ticket shortly with screenshots of all three dashboards (Gemini + Supabase + Railway). The evidence that this wasn’t legitimate usage is pretty clear-cut.

For anyone else reading this

Two PSAs if you’re shipping anything that touches a paid API:

  1. Never put a real API key behind a VITE_ / NEXT_PUBLIC_ / REACT_APP_ prefix. Those prefixes exist specifically to mark values as client-exposed. If the API bills on usage, the key MUST live server-side behind an authenticated proxy.

  2. Set a hard billing cap in Google Cloud (Billing → Budgets & Alerts → set action to disable billing at threshold). Had I done this, the damage would have capped at $50 instead of $2200.

Would love to hear from anyone who’s been through the credit process — any tips on what to include to speed things up?

Thanks
wandering_weasel

1 Like