Constructing an @upstash/ratelimit or express-rate-limit instance and never calling .limit() or app.use(rateLimit(...)) leaves your endpoints open to credential stuffing, enumeration, and API cost amplification. CWE-400 (Uncontrolled Resource Consumption) is the direct mapping. The library's presence in package.json signals the developer anticipated abuse — but without invocation, every endpoint accepts unlimited requests. An attacker who discovers the rate limiter is never called can run brute-force or scraping at full speed.
High because an unapplied rate limiter provides zero protection against brute-force, credential stuffing, and API resource exhaustion on every route.
Call .limit() per request at the top of each handler, or apply rateLimit() as global middleware. For Upstash:
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'
const limiter = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '10 s'),
})
export async function POST(req: Request) {
const ip = req.headers.get('x-forwarded-for') ?? 'anonymous'
const { success, remaining } = await limiter.limit(ip)
if (!success) {
return Response.json({ error: 'Too many requests' }, { status: 429 })
}
// ... rest of handler
}
For sensitive routes (login, password reset, signup), apply tighter limits than general API routes. Verify the .limit() call appears before any business logic.
ID: ai-slop-security-theater.unapplied-middleware.rate-limiter-imported-and-applied
Severity: high
What to look for: When any rate-limiting library is in package.json dependencies — express-rate-limit, @upstash/ratelimit, rate-limiter-flexible, rate-limit-redis, bottleneck, next-rate-limit, @vercel/firewall — walk source files and count all imports of these libraries. For each import, count whether the same file or another file in the application chain contains an INVOCATION pattern: app.use(rateLimit(, await ratelimit.limit(, await rateLimit.check(, await rateLimiter.consume(, bottleneck.schedule(, OR a middleware wrapper that the library documents.
Pass criteria: A rate-limiting library is imported AND at least 1 invocation call exists. Report: "Rate limiter: [name] imported in [file] AND invoked in [file]."
Fail criteria: A rate-limiting library is imported but never invoked anywhere in source.
Skip (N/A) when: No rate-limiting library in dependencies AND no vercel.json/netlify.toml/Cloudflare config defines rate limits.
Detail on fail: "@upstash/ratelimit imported in src/lib/ratelimit.ts but no .limit(... call found anywhere in source. Rate limiter constructed but never used to actually limit requests."
Remediation: A rate limiter that's never invoked doesn't limit anything. Wire it into your route handlers:
// Bad: limiter constructed but never called
import { Ratelimit } from '@upstash/ratelimit'
const limiter = new Ratelimit({ ... })
// ...no .limit() calls anywhere
// Good: invoke .limit() per request
export async function POST(req: Request) {
const ip = req.headers.get('x-forwarded-for') ?? 'anonymous'
const { success } = await limiter.limit(ip)
if (!success) {
return Response.json({ error: 'Too many requests' }, { status: 429 })
}
// ... handle request
}