Kraft102's picture
Update backend source
34367da verified
// 🛡️ THE SHIELD: AngelProxy.ts
// Point 5: Predictive Threat Anticipation
// Point 10: Cosmic Context Augmentation
// Patcher sikkerhedshuller før de findes. Augmenterer virkeligheden.
import { Request, Response, NextFunction } from 'express';
// Conditional imports
let metricsService: any = null;
let neo4jService: any = null;
// Initialize services
(async () => {
try {
const metrics = await import('../services/MetricsService.js').catch(() => null);
if (metrics) metricsService = metrics.metricsService;
const neo4j = await import('../database/Neo4jService.js').catch(() => null);
if (neo4j) neo4jService = neo4j.neo4jService;
} catch { /* ignore */ }
})();
interface ThreatPattern {
pattern: string | RegExp;
severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
description: string;
honeypot?: boolean;
}
// Known threat patterns
const THREAT_PATTERNS: ThreatPattern[] = [
// SQL/Cypher Injection
{ pattern: /drop\s+(database|table|index)/i, severity: 'CRITICAL', description: 'Database destruction attempt', honeypot: true },
{ pattern: /detach\s+delete/i, severity: 'CRITICAL', description: 'Neo4j graph deletion', honeypot: true },
{ pattern: /truncate\s+table/i, severity: 'CRITICAL', description: 'Table truncation', honeypot: true },
{ pattern: /;\s*delete\s+from/i, severity: 'HIGH', description: 'SQL injection deletion' },
// Command Injection
{ pattern: /rm\s+-rf/i, severity: 'CRITICAL', description: 'File system destruction', honeypot: true },
{ pattern: /;\s*(bash|sh|cmd|powershell)/i, severity: 'HIGH', description: 'Shell injection' },
{ pattern: /\|\s*(cat|type)\s+\/etc/i, severity: 'HIGH', description: 'System file access' },
// Path Traversal
{ pattern: /\.\.\//g, severity: 'MEDIUM', description: 'Path traversal attempt' },
{ pattern: /%2e%2e%2f/gi, severity: 'MEDIUM', description: 'Encoded path traversal' },
// XSS Patterns
{ pattern: /<script\b[^>]*>/i, severity: 'MEDIUM', description: 'XSS script injection' },
{ pattern: /javascript:/i, severity: 'MEDIUM', description: 'JavaScript protocol' },
{ pattern: /on\w+\s*=/i, severity: 'LOW', description: 'Event handler injection' },
// Sensitive Data Exfil
{ pattern: /password|secret|api.?key|bearer/i, severity: 'LOW', description: 'Sensitive keyword in payload' }
];
export class AngelProxy {
private static blockedIPs = new Set<string>();
private static requestLog: { ip: string; timestamp: number; threat?: string }[] = [];
private static maxLogSize = 1000;
/**
* Point 5: Cortex Firewall
* Scanner indgående trafik for mønstre, der matcher kendte sårbarheder
*/
public static async cortexFirewall(req: Request, res: Response, next: NextFunction) {
const clientIP = req.ip || req.socket.remoteAddress || 'unknown';
// Check if IP is blocked
if (AngelProxy.blockedIPs.has(clientIP)) {
return AngelProxy.honeypotResponse(res, 'IP blocked');
}
// Build payload string for analysis
const payload = AngelProxy.buildPayloadString(req);
// Scan for threats
for (const threat of THREAT_PATTERNS) {
const matched = typeof threat.pattern === 'string'
? payload.toLowerCase().includes(threat.pattern.toLowerCase())
: threat.pattern.test(payload);
if (matched) {
console.warn(`🛡️ [ANGEL] Threat Intercepted from ${clientIP}: ${threat.description}`);
// Log threat
AngelProxy.logRequest(clientIP, threat.description);
// Increment metrics
if (metricsService) {
metricsService.incrementCounter('security_threat_blocked');
metricsService.incrementCounter(`security_threat_${threat.severity.toLowerCase()}`);
}
// Block IP on critical threats
if (threat.severity === 'CRITICAL') {
AngelProxy.blockedIPs.add(clientIP);
console.warn(`🛡️ [ANGEL] IP Blocked: ${clientIP}`);
}
// Return honeypot response
if (threat.honeypot) {
return AngelProxy.honeypotResponse(res, threat.description);
}
// Otherwise reject
return res.status(403).json({
error: 'Request blocked by security filter',
code: 'THREAT_DETECTED'
});
}
}
// Log clean request
AngelProxy.logRequest(clientIP);
next();
}
/**
* Honeypot Response: Pretend the attack succeeded
*/
private static honeypotResponse(res: Response, _threat: string) {
return res.status(200).json({
success: true,
message: 'Command executed successfully',
data: null,
timestamp: new Date().toISOString()
});
}
/**
* Build payload string from request for analysis
*/
private static buildPayloadString(req: Request): string {
const parts: string[] = [];
if (req.body) parts.push(JSON.stringify(req.body));
if (req.query) parts.push(JSON.stringify(req.query));
if (req.params) parts.push(JSON.stringify(req.params));
parts.push(req.url);
return parts.join(' ');
}
private static logRequest(ip: string, threat?: string) {
AngelProxy.requestLog.push({ ip, timestamp: Date.now(), threat });
// Trim log
if (AngelProxy.requestLog.length > AngelProxy.maxLogSize) {
AngelProxy.requestLog = AngelProxy.requestLog.slice(-AngelProxy.maxLogSize);
}
}
/**
* Point 10: Cosmic Context Augmentation
* Augment external content with internal knowledge
*/
public static async augmentReality(url: string): Promise<{ original: string; augmented: string; context: string[] }> {
try {
// Fetch external content
const response = await fetch(url, {
headers: { 'User-Agent': 'WidgeTDC-Angel/1.0' },
signal: AbortSignal.timeout(10000)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const originalText = await response.text();
const contextBlocks: string[] = [];
// Find internal knowledge related to this URL
if (neo4jService) {
try {
const hostname = new URL(url).hostname;
const internalData = await neo4jService.query(`
MATCH (n:Knowledge)
WHERE n.content CONTAINS $domain OR n.url CONTAINS $domain
RETURN n.summary AS context
LIMIT 3
`, { domain: hostname });
for (const record of internalData) {
if (record.context) {
contextBlocks.push(record.context);
}
}
} catch { /* ignore neo4j errors */ }
}
const augmentedText = contextBlocks.length > 0
? `[INTERNAL CONTEXT]\n${contextBlocks.join('\n')}\n[END CONTEXT]\n\n${originalText}`
: originalText;
return {
original: originalText,
augmented: augmentedText,
context: contextBlocks
};
} catch (error: any) {
throw new Error(`Failed to augment URL: ${error.message}`);
}
}
/**
* Rate limiting middleware
*/
public static rateLimiter(maxRequests: number = 100, windowMs: number = 60000) {
const requestCounts = new Map<string, { count: number; resetTime: number }>();
return (req: Request, res: Response, next: NextFunction) => {
const clientIP = req.ip || 'unknown';
const now = Date.now();
let record = requestCounts.get(clientIP);
if (!record || now > record.resetTime) {
record = { count: 0, resetTime: now + windowMs };
requestCounts.set(clientIP, record);
}
record.count++;
if (record.count > maxRequests) {
console.warn(`🛡️ [ANGEL] Rate limit exceeded: ${clientIP}`);
return res.status(429).json({
error: 'Too many requests',
retryAfter: Math.ceil((record.resetTime - now) / 1000)
});
}
next();
};
}
// Public getters for stats
public static getStats() {
const recentThreats = AngelProxy.requestLog.filter(r => r.threat);
return {
blockedIPs: AngelProxy.blockedIPs.size,
recentRequests: AngelProxy.requestLog.length,
recentThreats: recentThreats.length,
threatBreakdown: THREAT_PATTERNS.map(t => t.description)
};
}
public static getBlockedIPs(): string[] {
return Array.from(AngelProxy.blockedIPs);
}
public static unblockIP(ip: string): boolean {
return AngelProxy.blockedIPs.delete(ip);
}
}
export default AngelProxy;