ShellCV implements multi-layered security to protect against abuse, API key exhaustion, and DDoS attacks.
Location: server.js (lines 10-58)
RATE_LIMIT = {
windowMs: 60 * 1000, // 1 minute window
maxRequests: 10, // Max 10 AI requests per minute per IP
message: 'Too many requests. Please try again in a minute.'
}- Tracks requests per IP address using in-memory Map
- Rolling window algorithm (1 minute)
- Returns HTTP 429 (Too Many Requests) when exceeded
- Includes
Retry-Afterheader for polite clients - Automatic cleanup of old entries every 5 minutes
const clientIp =
req.headers['x-forwarded-for']?.split(',')[0].trim() ||
req.headers['x-real-ip'] ||
req.socket.remoteAddress ||
'unknown';X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Requests left in current windowRetry-After: Seconds until limit resets
Location: server.js (lines 200-205)
- ✅ Question must be a string
- ✅ Question must not be empty
- ✅ Question must be ≤ 500 characters
- ✅ Returns HTTP 400 (Bad Request) if invalid
if (!question || typeof question !== 'string' || question.length > 500) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid question format (max 500 chars)' }));
return;
}Location: terminal.js (lines 213-220)
- Prevents same command from running within 1 second
- Improves UX by preventing accidental double-clicks
- Shows friendly warning message
Note: This is NOT a security measure (can be bypassed), but enhances user experience.
Location: terminal.js (lines 961-981)
⚠ Rate limit exceeded
Please wait 60 seconds before asking again
Try: 'help' or 'resume' for other ways to explore
⚠ AI agent temporarily unavailable
Try: 'help' or 'resume' for other ways to explore
Attack: Attacker sends 1000 requests/second to burn API quota
Protection:
- ✅ Rate limit blocks after 10 requests/minute
- ✅ Server logs suspicious activity
- ✅ Cleanup prevents memory exhaustion
Result: Only 10 requests processed, rest blocked with 429
Attack: Attacker uses botnet with 100 different IPs
Protection:
- ✅ Each IP tracked separately
- ✅ 10 requests/minute per IP = max 1000/min total
- ✅ Google Gemini free tier = 1500/day (safe)
Result: Attack contained within API limits
Attack: Attacker modifies terminal.js to bypass 1-second cooldown
Protection:
- ✅ Client-side check is just UX enhancement
- ✅ Server-side rate limit CANNOT be bypassed
- ✅ Attack still blocked after 10 requests
Result: Server-side protection holds
Attack: Attacker sends 10MB question to crash server
Protection:
- ✅ 500 character limit enforced server-side
- ✅ Returns 400 error immediately
- ✅ No AI processing wasted
Result: Request rejected before AI call
Attack: Attacker tries prompt injection or XSS
Protection:
- ✅ Question validated as string
- ✅ AI system prompt defines boundaries
- ✅ Frontend escapes HTML output
- ✅ No eval() or dangerous operations
Result: Safe handling of malicious input
- ✅ Rate limit exceeded:
⚠️ Rate limit exceeded for IP: x.x.x.x - ✅ Successful request:
✅ AI request from x.x.x.x: "question..." - ✅ AI errors:
AI Agent error: [details]
✅ AI request from 127.0.0.1: "what did Amit do at SentinelOne?..."
✅ AI request from 127.0.0.1: "tell me about projects..."
⚠️ Rate limit exceeded for IP: 127.0.0.1
- ✅
GOOGLE_GENERATIVE_AI_API_KEYstored in.env - ✅
.envin.gitignore(never committed) - ✅ Server-side only (never exposed to frontend)
- Google Gemini Free Tier: 1,500 requests/day
- ShellCV Rate Limit: 10 requests/minute per IP
- Max Daily Load: ~14,400 requests (24h * 60min * 10 req)
- Protection: Rate limit prevents quota exhaustion
When deploying to production:
-
Set Environment Variable:
GOOGLE_GENERATIVE_AI_API_KEY=your_key_here
-
Rate Limit Auto-Applied:
- No additional configuration needed
- Works with edge functions
- Handles proxy headers automatically
-
Monitor Usage:
- Check server logs for rate limit hits
- Monitor Google AI Studio for API usage
- Set up alerts if approaching limits
// For high-traffic sites, consider:
RATE_LIMIT = {
windowMs: 60 * 1000,
maxRequests: 5, // Lower for production
message: 'Too many requests. Please try again later.'
}# Send 12 rapid requests (10 should succeed, 2 blocked)
for i in {1..12}; do
curl -X POST http://localhost:3333/api/ask \
-H "Content-Type: application/json" \
-d '{"question":"test"}' | jq -r '.error // .answer'
done- Requests 1-10: AI responses
- Requests 11-12: "Too many requests. Please try again in a minute."
- Rate Limit Map: ~100 bytes per IP
- 1000 IPs: ~100KB memory
- Cleanup: Every 5 minutes
- Rate Check: <1ms overhead
- Total Impact: Negligible
- Server-side rate limiting implemented
- Input validation on all API endpoints
- API key stored securely in
.env - API key never exposed to frontend
- Client IP detection handles proxies
- Error messages don't leak sensitive info
- Logging tracks suspicious activity
- Cleanup prevents memory leaks
- Graceful degradation on errors
- Rate limit headers included
- Check server logs for IP patterns
- Lower
maxRequestsif needed - Consider implementing IP whitelist/blacklist
- Contact Google for quota increase
- Check rate limit logs
- Temporarily disable
/api/askendpoint - Use Cloudflare/similar for DDoS protection
- Whitelist known good IPs if needed
Last Updated: Oct 2024 Maintained By: Amit Yogev Security Contact: amit.yogev@gmail.com