API Rate Limit Bypass: Secure Your Vibe-Coded App
OverMCP Team
Quick answer
API rate limit bypass happens when an attacker circumvents your app's request limits by rotating IP addresses, manipulating headers, or exploiting missing authentication checks. To fix it, implement rate limiting on your backend using a sliding window algorithm, always authenticate requests before applying limits, and use a centralized store like Redis for distributed apps.
Why vibe-coded apps are vulnerable to rate limit bypass
When you build an app fast with AI coding tools, the generated code often includes a simple rate limiter—if any at all. You might get a middleware that counts requests per IP in a local object, which works fine on your local machine. But once deployed, that in-memory store resets on every server restart or fails across multiple instances. Worse, the limiter might only check IP addresses, which attackers can easily spoof via the X-Forwarded-For header. This is one of the most common API rate limit bypass vulnerabilities in AI-built apps.
What to check first
Before diving into fixes, audit your current implementation with this checklist:
req.ip or req.connection.remoteAddress?X-Forwarded-For header?Common mistakes in AI-generated apps
1. Using local in-memory storage
Most AI-generated rate limiters use a simple JavaScript object or Map to store request counts. This works in development but resets on server restart and doesn't scale across multiple instances. An attacker can simply wait for a restart or hit different server instances to bypass limits.
2. Trusting client IP headers blindly
Many apps read the IP from req.headers['x-forwarded-for'] without validation. Attackers can send a fake header to impersonate other users or reset their own limit. Always use the last IP in the chain (the one added by your proxy) or trust only the direct connection IP.
3. Not differentiating between authenticated and unauthenticated requests
If your rate limiter counts all requests before authentication, an attacker can exhaust the global limit and deny service to legitimate users. Apply stricter limits on unauthenticated endpoints and use user IDs for authenticated ones.
4. Ignoring distributed denial of service (DDoS) via slow loris attacks
AI-coded apps often miss connection-level rate limiting. An attacker can open many slow connections that stay alive, consuming server resources. Use a reverse proxy like NGINX or a web application firewall (WAF) to cap concurrent connections.
Step-by-step fix
Step 1: Choose a centralized store
Replace local in-memory storage with Redis or a database. For Node.js apps, use express-rate-limit with rate-limit-redis:
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');
const redisClient = new Redis(process.env.REDIS_URL);
const limiter = rateLimit({
store: new RedisStore({
client: redisClient,
prefix: 'rate-limit:',
}),
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later.',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);Step 2: Validate IP headers
Configure your proxy (e.g., NGINX, Vercel) to set a trusted header. In Express, trust the proxy:
app.set('trust proxy', 1);Then use req.ip which returns the correct IP. If you must parse X-Forwarded-For, take the rightmost IP (the one added by your proxy).
Step 3: Apply per-user limits after authentication
Create separate limiters for authenticated and unauthenticated routes:
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
keyGenerator: (req) => req.user ? req.user.id : req.ip,
});
app.use('/api/', apiLimiter);For stricter login limits, use a smaller window:
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true,
});
app.post('/api/login', loginLimiter, loginHandler);Step 4: Add connection-level limiting (optional but recommended)
If you're using NGINX, add:
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;Step 5: Monitor and alert
Use a service like OverMCP's continuous security monitoring to detect unusual traffic spikes that might indicate a bypass attempt. You can also set up logging for rate limit hits and review them regularly.
Testing your fix
Deploy the changes and test with these scenarios:
X-Forwarded-For header – the limiter should still use the real IP.How OverMCP helps
Instead of manually checking each endpoint, you can scan your app for free with OverMCP's security scanner. It will detect missing rate limiting, misconfigured IP trust, and other common vulnerabilities in vibe-coded apps. After fixing, run a security headers check to ensure your app is hardened against other attacks.
FAQ
Can API rate limit bypass lead to account takeover?
Yes, if combined with brute-force attacks on login endpoints without proper per-user rate limiting, an attacker can bypass IP-based limits and guess passwords. Always use per-user limits and account lockout mechanisms.
Does using a serverless platform like Vercel protect me?
Vercel provides some DDoS protection at the edge, but application-level rate limiting is still your responsibility. Without it, your API can be abused for scraping or data exfiltration. Use their @vercel/edge rate limiting or implement your own.
How do I test if my app is vulnerable to rate limit bypass?
Try sending requests with different X-Forwarded-For values using a tool like curl or Postman. If you see different rate limit responses, you're vulnerable. Also check if the limit resets on server restart or across different regions.
---
By following this guide, you can prevent API rate limit bypass in your vibe-coded app and protect it from abuse. For a full security audit, use OverMCP's free scanner to catch other issues like leaked secrets or missing headers.