Status: Observability Only (No Blocking)
Issue: #181
Lightweight abuse detection system that tracks suspicious patterns and logs signals without blocking legitimate traffic. Designed for observability and future integration with blocking mechanisms.
Tracks request volume per IP address within a time window.
Threshold: 100 requests per minute
Action: Flag IP and log warning
No blocking: Traffic continues normally
Tracks failed requests (4xx/5xx responses) per IP address.
Threshold: 20 failures per 5 minutes
Action: Flag IP and log warning
No blocking: Traffic continues normally
Flagged IPs are automatically unflagged after 1 hour cooldown period.
Request → Middleware → Track Request → Check Thresholds → Flag if Exceeded
↓
Log Warning
↓
Add Header (X-Abuse-Signal)
↓
Continue Processing
Located in src/utils/abuseDetector.js:
{
burstThreshold: 100, // requests per window
burstWindow: 60000, // 1 minute
failureThreshold: 20, // failures per window
failureWindow: 300000, // 5 minutes
cleanupInterval: 600000 // 10 minutes
}The middleware automatically tracks all requests:
// In src/app.js
app.use(abuseDetectionMiddleware);Admin-only endpoint to view current statistics:
GET /abuse-signals
Authorization: x-api-key: <admin-key>
Response:
{
"success": true,
"data": {
"suspiciousIPs": 3,
"trackedIPs": 150,
"failureTracking": 45
},
"timestamp": "2026-02-25T01:00:00.000Z"
}Flagged IPs receive a header for observability:
X-Abuse-Signal: flagged
{
"level": "WARN",
"scope": "ABUSE_DETECTION",
"message": "Suspicious activity detected: request_burst",
"ip": "192.168.1.100",
"signal": "request_burst",
"count": 105,
"threshold": 100,
"window": 60000,
"timestamp": "2026-02-25T01:00:00.000Z"
}{
"level": "WARN",
"scope": "ABUSE_DETECTION",
"message": "Suspicious activity detected: repeated_failures",
"ip": "192.168.1.101",
"signal": "repeated_failures",
"count": 25,
"threshold": 20,
"window": 300000,
"reason": "client_error",
"timestamp": "2026-02-25T01:00:00.000Z"
}Search logs for abuse signals:
# Find all abuse signals
grep "ABUSE_DETECTION" logs/app.log
# Find specific signal types
grep "request_burst" logs/app.log
grep "repeated_failures" logs/app.log
# Find flagged IPs
grep "Suspicious activity detected" logs/app.log | jq '.ip'Track these metrics in your monitoring system:
abuse.suspicious_ips- Number of flagged IPsabuse.tracked_ips- Total IPs being trackedabuse.burst_signals- Count of burst signalsabuse.failure_signals- Count of failure signals
- High Thresholds: Conservative limits reduce false positives
- No Blocking: Legitimate traffic never interrupted
- Auto-Unflagging: 1-hour cooldown prevents permanent flags
- Observability First: Review logs before implementing blocks
Adjust thresholds based on your traffic patterns:
// For high-traffic APIs
burstThreshold: 200
failureThreshold: 50
// For low-traffic APIs
burstThreshold: 50
failureThreshold: 10Current implementation uses in-memory storage. For production:
// Use Redis for distributed tracking
const redis = require('redis');
const client = redis.createClient();
// Store counts in Redis with TTL
await client.setex(`abuse:req:${ip}`, 60, count);For multi-instance deployments:
- Use shared Redis/Memcached
- Aggregate signals across instances
- Centralized monitoring dashboard
Export signals to Web Application Firewall:
// Send to WAF
if (abuseDetector.isSuspicious(ip)) {
await waf.addToWatchlist(ip, { reason: signal, ttl: 3600 });
}Run abuse detection tests:
npm test tests/abuse-detection.test.jsTest coverage:
- Request burst detection
- Failure tracking
- Threshold enforcement
- Cleanup mechanisms
- Edge cases (null IPs, etc.)
- Rate Limiting Integration: Auto-apply stricter limits to flagged IPs
- Machine Learning: Pattern recognition for sophisticated attacks
- Geo-blocking: Track suspicious regions
- API Key Correlation: Link abuse to specific API keys
- Automated Blocking: Optional blocking mode with safeguards
✅ No false blocking - traffic never interrupted
✅ Signals are observable - logs and endpoint available
✅ Privacy-friendly - only tracks IPs, no PII
✅ Configurable - thresholds adjustable per environment
✅ Automatic cleanup - no indefinite tracking
For issues or questions:
- Check logs:
grep ABUSE_DETECTION logs/app.log - View stats:
GET /abuse-signals - Adjust config:
src/utils/abuseDetector.js