Spaces:
Running
Running
| /** | |
| * APPLICATION FIREWALL - Tier 1 | |
| * Client-side WAF with rate limiting, input sanitization, and behavioral analysis | |
| */ | |
| class IronFirewall { | |
| constructor() { | |
| this.rules = new Map(); | |
| this.rateLimiters = new Map(); | |
| this.threatScore = 0; | |
| this.blockedIPs = new Set(); // Simulated IP blocking via fingerprinting | |
| this.requestLog = []; | |
| this.initRules(); | |
| this.startBehavioralAnalysis(); | |
| } | |
| initRules() { | |
| // Rule Set 1: Rate Limiting per action type | |
| this.rules.set('API_CALL', { max: 10, window: 60000 }); // 10 calls per minute | |
| this.rules.set('LOGIN_ATTEMPT', { max: 3, window: 300000 }); // 3 per 5min | |
| this.rules.set('DATA_EXPORT', { max: 1, window: 3600000 }); // 1 per hour | |
| // Rule Set 2: Content Filtering (XSS, Injection) | |
| this.rules.set('XSS_PATTERN', /<(script|img|svg)[^>]*>/gi); | |
| this.rules.set('SQL_PATTERN', /(\b(SELECT|INSERT|UPDATE|DELETE|DROP)\b)|(--|\/\*|\*\/)/gi); | |
| this.rules.set('PATH_TRAVERSAL', /\.\.\/|\\..\\|\.\.\\/g; | |
| } | |
| checkRateLimit(actionType, identifier) { | |
| const key = `${actionType}_${identifier}`; | |
| const limit = this.rules.get(actionType); | |
| if (!limit) return { allowed: true }; | |
| const now = Date.now(); | |
| if (!this.rateLimiters.has(key)) { | |
| this.rateLimiters.set(key, { count: 1, startTime: now }); | |
| return { allowed: true, remaining: limit.max - 1 }; | |
| } | |
| const record = this.rateLimiters.get(key); | |
| if (now - record.startTime > limit.window) { | |
| // Reset window | |
| record.count = 1; | |
| record.startTime = now; | |
| return { allowed: true, remaining: limit.max - 1 }; | |
| } | |
| record.count++; | |
| if (record.count > limit.max) { | |
| this.threatScore += 10; | |
| return { | |
| allowed: false, | |
| reason: 'RATE_LIMIT_EXCEEDED', | |
| retryAfter: Math.ceil((record.startTime + limit.window - now) / 1000) | |
| }; | |
| } | |
| return { allowed: true, remaining: limit.max - record.count }; | |
| } | |
| sanitizeInput(input, context = 'general') { | |
| let sanitized = input; | |
| let threats = []; | |
| // XSS Detection | |
| if (this.rules.get('XSS_PATTERN').test(input)) { | |
| threats.push('XSS_ATTEMPT'); | |
| sanitized = sanitized.replace(this.rules.get('XSS_PATTERN'), '[XSS_BLOCKED]'); | |
| } | |
| // SQL Injection Detection | |
| if (this.rules.get('SQL_PATTERN').test(input)) { | |
| threats.push('SQL_INJECTION'); | |
| sanitized = sanitized.replace(this.rules.get('SQL_PATTERN'), ''); | |
| } | |
| // Path Traversal | |
| if (this.rules.get('PATH_TRAVERSAL').test(input)) { | |
| threats.push('PATH_TRAVERSAL'); | |
| this.threatScore += 25; | |
| } | |
| if (threats.length > 0) { | |
| this.logThreat({ type: 'INPUT_VIOLATION', threats, input: input.substring(0, 100) }); | |
| } | |
| return { sanitized, threats, safe: threats.length === 0 }; | |
| } | |
| validateClassificationAccess(requiredLevel, userLevel) { | |
| const levels = ['PUBLIC', 'RESTREINT', 'CONFIDENTIEL', 'SECRET', 'TOP_SECRET']; | |
| const reqIdx = levels.indexOf(requiredLevel); | |
| const userIdx = levels.indexOf(userLevel); | |
| if (userIdx < reqIdx) { | |
| this.threatScore += 50; // Serious breach attempt | |
| this.logThreat({ | |
| type: 'CLASSIFICATION_BREACH_ATTEMPT', | |
| required: requiredLevel, | |
| user: userLevel | |
| }); | |
| return { authorized: false, action: 'LOGGED_AND_BLOCKED' }; | |
| } | |
| return { authorized: true }; | |
| } | |
| startBehavioralAnalysis() { | |
| // Monitor for automated behavior (bots) | |
| let mouseEvents = 0; | |
| let keyEvents = 0; | |
| document.addEventListener('mousemove', () => mouseEvents++); | |
| document.addEventListener('keydown', () => keyEvents++); | |
| setInterval(() => { | |
| // If no human-like interaction but API calls are happening = bot | |
| if (this.apiCallsInLastMinute > 20 && mouseEvents < 2) { | |
| this.threatScore += 30; | |
| this.logThreat({ type: 'SUSPECTED_BOT', mouseEvents, apiCalls: this.apiCallsInLastMinute }); | |
| } | |
| mouseEvents = 0; | |
| keyEvents = 0; | |
| this.apiCallsInLastMinute = 0; | |
| }, 60000); | |
| } | |
| logThreat(details) { | |
| const entry = { | |
| timestamp: new Date().toISOString(), | |
| ...details, | |
| score: this.threatScore, | |
| fingerprint: this.generateFingerprint() | |
| }; | |
| this.requestLog.push(entry); | |
| window.federationBus?.emit('SECURITY_THREAT', entry); | |
| if (this.threatScore > 100) { | |
| this.triggerLockdown(); | |
| } | |
| } | |
| generateFingerprint() { | |
| // Simple browser fingerprinting for session tracking | |
| return btoa(`${navigator.userAgent}${screen.width}x${screen.height}${navigator.language}`); | |
| } | |
| triggerLockdown() { | |
| window.federationBus?.emit('SYSTEM_LOCKDOWN', { | |
| reason: 'THREAT_THRESHOLD_EXCEEDED', | |
| score: this.threatScore, | |
| timestamp: Date.now() | |
| }); | |
| // Disable all inputs | |
| document.querySelectorAll('input, button, textarea').forEach(el => { | |
| if (!el.dataset.essential) el.disabled = true; | |
| }); | |
| showToast('🔒 SYSTEM LOCKDOWN ACTIVATED - Contact Administrator', 'error'); | |
| } | |
| // API middleware wrapper | |
| async secureFetch(url, options = {}) { | |
| this.apiCallsInLastMinute = (this.apiCallsInLastMinute || 0) + 1; | |
| const rateCheck = this.checkRateLimit('API_CALL', 'global'); | |
| if (!rateCheck.allowed) { | |
| throw new Error(`Rate limit exceeded. Retry after ${rateCheck.retryAfter}s`); | |
| } | |
| // Add security headers | |
| const secureOptions = { | |
| ...options, | |
| headers: { | |
| ...options.headers, | |
| 'X-Request-ID': crypto.randomUUID(), | |
| 'X-Fingerprint': this.generateFingerprint(), | |
| 'X-Threat-Score': this.threatScore | |
| } | |
| }; | |
| try { | |
| const response = await fetch(url, secureOptions); | |
| if (!response.ok && response.status === 429) { | |
| this.threatScore += 5; // Penalty for hitting server limits | |
| } | |
| return response; | |
| } catch (err) { | |
| this.logThreat({ type: 'NETWORK_ERROR', error: err.message }); | |
| throw err; | |
| } | |
| } | |
| } | |
| window.ironFirewall = new IronFirewall(); |