How API Abuse Nearly Bankrupted Our Startup

Share

TL;DR

Someone discovered our /api/generate endpoint had no authentication or rate limiting. Over a weekend, they made millions of requests using our OpenAI API key. We woke up Monday to a $47,000 bill. After lengthy negotiations, OpenAI forgave most of the charges, but only after we proved we'd implemented proper protections.

On Monday morning, I opened an email from OpenAI with the subject line "Usage Alert - Action Required." The number inside made me physically ill.

The Horrifying Discovery

$47K
OpenAI charges
3.2M
API requests
48 hrs
Duration
$500
Our normal monthly bill

Our typical OpenAI bill was $500/month. This weekend had generated nearly 100x that amount. Someone had found our AI endpoint and used it as their personal GPT-4 server.

"I remember sitting in my car in the parking lot, unable to go into the office. We had maybe $20K in the bank. This bill alone would wipe us out and then some."

How They Found Us

We built an AI writing assistant. The frontend sent requests to /api/generate which proxied to OpenAI. Simple, clean, and completely unprotected.

// Our original (terrible) endpoint
app.post('/api/generate', async (req, res) => {
  const { prompt } = req.body;

  // No auth check. No rate limit. Just vibes.
  const completion = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: prompt }]
  });

  res.json(completion);
});

The attacker probably found us through:

  • Scanning JavaScript bundles for API endpoints
  • Checking network requests in browser dev tools
  • Automated scanners looking for unprotected AI endpoints

Once they found a working endpoint, they set up a script to pump through requests 24/7.

Our Mistakes

  • No authentication required to use the endpoint
  • No rate limiting whatsoever
  • No usage caps or spending alerts set up
  • No monitoring for unusual usage patterns
  • Using GPT-4 (expensive) instead of GPT-3.5 where appropriate

The Recovery

I immediately rotated the API key to stop the bleeding. Then began the painful process of dealing with the bill.

OpenAI support was understanding but needed assurance this wouldn't happen again. We documented everything:

  • Proof that requests came from unknown IPs, not our users
  • Our new authentication and rate limiting implementation
  • Spending alerts configured at multiple thresholds
  • Monthly spending caps enabled

After two weeks of back-and-forth, they forgave $42,000 of the charges. We still paid $5,000, which was painful but survivable.

The Fix

// The secure version
import { rateLimit } from 'express-rate-limit';
import { authMiddleware } from './auth';

const aiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 10, // 10 requests per minute per user
  message: 'Too many requests, please slow down'
});

app.post('/api/generate',
  authMiddleware,        // Require login
  aiLimiter,             // Rate limit
  usageTracker,          // Track per-user usage
  async (req, res) => {
    const user = req.user;

    // Check user's remaining quota
    if (user.aiCredits <= 0) {
      return res.status(403).json({
        error: 'Usage limit reached'
      });
    }

    // Process request...
    await decrementUserCredits(user.id);
});

We also set up proper OpenAI spending controls:

  • Hard spending cap: $1,000/month maximum
  • Email alerts: At $100, $300, $500, $800
  • Daily monitoring: Automated checks for unusual spikes
  • Per-user limits: Maximum requests per user per day
Key Lessons Learned
  • Always authenticate API endpoints, especially ones that cost money
  • Implement rate limiting on all public-facing endpoints
  • Set spending caps and alerts with your API providers
  • Track per-user usage to catch abuse early
  • Use the cheapest appropriate model for each task
  • Monitor for unusual patterns - weekend spikes should trigger alerts

Will OpenAI forgive fraudulent charges?

They evaluate case by case. You'll need to prove it was abuse (not legitimate usage), show what security measures you've implemented, and work with their support team. They're generally understanding but don't guarantee forgiveness.

::

How do attackers find unprotected AI endpoints?

They scan JavaScript bundles for API routes, monitor network traffic on popular AI apps, use automated scanners, and share discovered endpoints in underground communities. If your endpoint is public and unprotected, assume it will be found.

What's a reasonable rate limit for AI endpoints?

It depends on your use case, but for most apps: 10-20 requests per minute per authenticated user is reasonable. For anonymous/trial users, consider 3-5 requests per hour. Always combine with authentication and per-user quotas.

::

Scan your vibe coded projects for unprotected APIs and missing rate limits.

Check Your Vibe Now
Security Stories

How API Abuse Nearly Bankrupted Our Startup