From harness-claude
Implements rate limiting, throttling, and abuse prevention for APIs. Covers multi-layer limits, Redis-backed distributed rate limiting, and progressive delays for failed authentication.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:owasp-rate-limitingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Protect APIs with rate limiting, throttling, and abuse prevention to mitigate brute force, scraping, and denial of service
Protect APIs with rate limiting, throttling, and abuse prevention to mitigate brute force, scraping, and denial of service
import rateLimit from 'express-rate-limit';
// General API rate limit
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per window
standardHeaders: true, // Return rate limit info in RateLimit-* headers
legacyHeaders: false,
message: { error: 'Too many requests. Please try again later.' },
});
// Strict limit for authentication endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 10, // 10 login attempts per 15 minutes
skipSuccessfulRequests: true, // Only count failed attempts
keyGenerator: (req) => req.body?.email ?? req.ip, // Rate limit per email, not just IP
});
// Strict limit for password reset
const resetLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 3, // 3 reset requests per hour
});
app.use('/api/', apiLimiter);
app.post('/api/auth/login', authLimiter, loginHandler);
app.post('/api/auth/reset-password', resetLimiter, resetHandler);
import { RedisStore } from 'rate-limit-redis';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
store: new RedisStore({
sendCommand: (...args: string[]) => redis.call(...args),
}),
});
async function loginWithProgressiveDelay(email: string, password: string, ip: string) {
const key = `login_attempts:${email}`;
const attempts = await redis.incr(key);
await redis.expire(key, 3600); // Reset after 1 hour
if (attempts > 10) {
throw new TooManyRequestsError('Account temporarily locked. Try again in 1 hour.');
}
if (attempts > 3) {
// Progressive delay: 1s, 2s, 4s, 8s...
const delayMs = Math.min(1000 * Math.pow(2, attempts - 4), 30000);
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
const user = await authenticate(email, password);
if (user) {
await redis.del(key); // Reset on success
return user;
}
logger.warn({ event: 'auth.login.failure', email, ip, attempts }, 'Login failed');
throw new UnauthorizedError('Invalid credentials');
}
RateLimit-Limit: 100
RateLimit-Remaining: 42
RateLimit-Reset: 1620000000
Retry-After: 120
const keyGenerator = (req: Request) => {
return req.user?.id ?? req.ip;
};
import { RateLimiterRedis } from 'rate-limiter-flexible';
const rateLimiter = new RateLimiterRedis({
storeClient: redis,
keyPrefix: 'api_limit',
points: 100, // 100 requests
duration: 60, // per 60 seconds
blockDuration: 60, // block for 60 seconds if exceeded
execEvenly: true, // distribute points evenly over duration
});
app.use(async (req, res, next) => {
try {
const key = req.user?.id ?? req.ip;
const result = await rateLimiter.consume(key);
res.setHeader('RateLimit-Limit', 100);
res.setHeader('RateLimit-Remaining', result.remainingPoints);
res.setHeader('RateLimit-Reset', new Date(Date.now() + result.msBeforeNext).toISOString());
next();
} catch (rejRes) {
res.status(429).json({
error: 'Too many requests',
retryAfter: Math.ceil(rejRes.msBeforeNext / 1000),
});
}
});
const costs: Record<string, number> = {
'GET /api/users/:id': 1,
'GET /api/search': 5,
'POST /api/export': 20,
'POST /api/upload': 10,
};
app.use(async (req, res, next) => {
const routeKey = `${req.method} ${req.route?.path ?? req.path}`;
const cost = costs[routeKey] ?? 1;
try {
await rateLimiter.consume(req.user?.id ?? req.ip, cost);
next();
} catch {
res.status(429).json({ error: 'Rate limit exceeded' });
}
});
Rate limiting algorithms:
Where to rate limit:
Layer 1-2 for DDoS protection, Layer 3-4 for business logic rate limiting.
Common mistakes:
https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeEnforces per-client request quotas using token bucket or sliding window algorithms to protect APIs from abuse, brute force, and resource exhaustion.
Controls request throughput with token bucket, sliding window, and fixed window algorithms to protect APIs from abuse, enforce usage quotas, and prevent service overload using Redis.
Implements API rate limiting and throttling using token bucket, sliding window, and fixed window algorithms with Redis-backed counters. Protects against brute force, credential stuffing, and API abuse.