Skip to content

Security: broddo-baggins/shellcv-template

Security

docs/SECURITY.md

Security & Anti-Abuse Protection

Overview

ShellCV implements multi-layered security to protect against abuse, API key exhaustion, and DDoS attacks.

🛡️ Protection Layers

1. SERVER-SIDE Rate Limiting (Primary Defense)

Location: server.js (lines 10-58)

Configuration

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.'
}

How it Works

  • Tracks requests per IP address using in-memory Map
  • Rolling window algorithm (1 minute)
  • Returns HTTP 429 (Too Many Requests) when exceeded
  • Includes Retry-After header for polite clients
  • Automatic cleanup of old entries every 5 minutes

IP Detection (Handles Proxies)

const clientIp = 
  req.headers['x-forwarded-for']?.split(',')[0].trim() || 
  req.headers['x-real-ip'] || 
  req.socket.remoteAddress || 
  'unknown';

Response Headers

  • X-RateLimit-Limit: Maximum requests allowed
  • X-RateLimit-Remaining: Requests left in current window
  • Retry-After: Seconds until limit resets

2. Input Validation (Data Sanitization)

Location: server.js (lines 200-205)

Checks

  • ✅ Question must be a string
  • ✅ Question must not be empty
  • ✅ Question must be ≤ 500 characters
  • ✅ Returns HTTP 400 (Bad Request) if invalid

Example

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;
}

3. Client-Side Throttling (UX Layer)

Location: terminal.js (lines 213-220)

Spam Prevention

  • 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.

4. Graceful Error Handling

Location: terminal.js (lines 961-981)

Rate Limit Exceeded (429)

⚠ Rate limit exceeded
Please wait 60 seconds before asking again
Try: 'help' or 'resume' for other ways to explore

AI Agent Down (500/Network Error)

⚠ AI agent temporarily unavailable
Try: 'help' or 'resume' for other ways to explore

🚨 Attack Scenarios & Mitigation

Scenario 1: Brute Force AI Spam

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

Scenario 2: Distributed Attack (Multiple IPs)

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

Scenario 3: Client-Side Bypass

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

Scenario 4: Extremely Long Questions

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

Scenario 5: Malicious Question Injection

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

📊 Monitoring & Logging

Server Logs

  • ✅ 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]

Example Log Output

✅ 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

🔐 API Key Protection

Environment Variables

  • GOOGLE_GENERATIVE_AI_API_KEY stored in .env
  • .env in .gitignore (never committed)
  • ✅ Server-side only (never exposed to frontend)

Key Usage Limits

  • 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

🚀 Production Deployment

Vercel/Railway/Render

When deploying to production:

  1. Set Environment Variable:

    GOOGLE_GENERATIVE_AI_API_KEY=your_key_here
  2. Rate Limit Auto-Applied:

    • No additional configuration needed
    • Works with edge functions
    • Handles proxy headers automatically
  3. Monitor Usage:

    • Check server logs for rate limit hits
    • Monitor Google AI Studio for API usage
    • Set up alerts if approaching limits

Recommended Settings

// For high-traffic sites, consider:
RATE_LIMIT = {
  windowMs: 60 * 1000,
  maxRequests: 5,  // Lower for production
  message: 'Too many requests. Please try again later.'
}

🧪 Testing Rate Limits

Manual Test

# 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

Expected Result

  • Requests 1-10: AI responses
  • Requests 11-12: "Too many requests. Please try again in a minute."

📈 Performance Impact

Memory Usage

  • Rate Limit Map: ~100 bytes per IP
  • 1000 IPs: ~100KB memory
  • Cleanup: Every 5 minutes

Latency

  • Rate Check: <1ms overhead
  • Total Impact: Negligible

✅ Security Checklist

  • 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

🆘 Incident Response

If API Quota Exhausted

  1. Check server logs for IP patterns
  2. Lower maxRequests if needed
  3. Consider implementing IP whitelist/blacklist
  4. Contact Google for quota increase

If Under DDoS

  1. Check rate limit logs
  2. Temporarily disable /api/ask endpoint
  3. Use Cloudflare/similar for DDoS protection
  4. Whitelist known good IPs if needed

📚 Further Reading


Last Updated: Oct 2024 Maintained By: Amit Yogev Security Contact: amit.yogev@gmail.com

There aren't any published security advisories