UNPKG

aimless-security

Version:

Enhanced Runtime Application Self-Protection (RASP) and API Fuzzing Engine with advanced threat detection, behavioral analysis, and intelligent response scoring for Node.js applications

172 lines 7.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebhookNotifier = void 0; class WebhookNotifier { constructor(url, events = ['all'], includePayload = false, customHeaders = {}, logger) { this.queue = []; this.processing = false; this.url = url; this.events = new Set(events.includes('all') ? ['block', 'threat', 'rateLimit'] : events); this.includePayload = includePayload; this.customHeaders = customHeaders; this.logger = logger; } async notify(payload) { // Check if event should be sent if (!this.events.has(payload.event)) { return; } // Remove payload if not configured to include if (!this.includePayload) { payload = { ...payload, payload: undefined }; } // Add to queue this.queue.push(payload); // Process queue if (!this.processing) { this.processQueue(); } } async processQueue() { this.processing = true; while (this.queue.length > 0) { const payload = this.queue.shift(); try { await this.sendWebhook(payload); } catch (error) { this.logger.error('Webhook delivery failed:', error); // Retry once after 5 seconds setTimeout(async () => { try { await this.sendWebhook(payload); } catch (retryError) { this.logger.error('Webhook retry failed:', retryError); } }, 5000); } // Rate limit: 1 webhook per 100ms await new Promise(resolve => setTimeout(resolve, 100)); } this.processing = false; } async sendWebhook(payload) { const body = JSON.stringify({ ...payload, source: 'Aimless Security', version: '1.3.4' }); const headers = { 'Content-Type': 'application/json', 'User-Agent': 'Aimless-Security/1.3.4', ...this.customHeaders }; // Detect webhook type and format accordingly if (this.url.includes('slack.com')) { await this.sendSlackWebhook(payload); } else if (this.url.includes('discord.com')) { await this.sendDiscordWebhook(payload); } else { // Generic webhook const response = await fetch(this.url, { method: 'POST', headers, body }); if (!response.ok) { throw new Error(`Webhook failed: ${response.status} ${response.statusText}`); } } } async sendSlackWebhook(payload) { const color = payload.event === 'block' ? '#dc2626' : payload.event === 'rateLimit' ? '#f59e0b' : '#ef4444'; const emoji = payload.event === 'block' ? '🛡️' : payload.event === 'rateLimit' ? '⚠️' : '🚨'; const text = payload.event === 'block' ? `*Security Threat Blocked*` : payload.event === 'rateLimit' ? `*Rate Limit Exceeded*` : `*Security Threat Detected*`; const slackPayload = { attachments: [{ color, title: `${emoji} ${text}`, fields: [ { title: 'IP Address', value: payload.ip, short: true }, { title: 'Path', value: payload.path, short: true }, { title: 'Method', value: payload.method, short: true }, { title: 'Timestamp', value: payload.timestamp.toISOString(), short: true }, ...(payload.threats && payload.threats.length > 0 ? [{ title: 'Threats', value: payload.threats.map(t => `• ${t.type} (${t.severity})`).join('\n'), short: false }] : []), ...(payload.reputation !== undefined ? [{ title: 'IP Reputation', value: `${payload.reputation}/100`, short: true }] : []) ], footer: 'Aimless Security', ts: Math.floor(payload.timestamp.getTime() / 1000) }] }; const response = await fetch(this.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(slackPayload) }); if (!response.ok) { throw new Error(`Slack webhook failed: ${response.status}`); } } async sendDiscordWebhook(payload) { const color = payload.event === 'block' ? 0xdc2626 : payload.event === 'rateLimit' ? 0xf59e0b : 0xef4444; const title = payload.event === 'block' ? '🛡️ Security Threat Blocked' : payload.event === 'rateLimit' ? '⚠️ Rate Limit Exceeded' : '🚨 Security Threat Detected'; const discordPayload = { embeds: [{ title, color, fields: [ { name: 'IP Address', value: payload.ip, inline: true }, { name: 'Path', value: payload.path, inline: true }, { name: 'Method', value: payload.method, inline: true }, { name: 'Timestamp', value: payload.timestamp.toISOString(), inline: true }, ...(payload.threats && payload.threats.length > 0 ? [{ name: 'Threats', value: payload.threats.map(t => `• ${t.type} (${t.severity})`).join('\n'), inline: false }] : []), ...(payload.reputation !== undefined ? [{ name: 'IP Reputation', value: `${payload.reputation}/100`, inline: true }] : []) ], footer: { text: 'Aimless Security v1.3.4' }, timestamp: payload.timestamp.toISOString() }] }; const response = await fetch(this.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(discordPayload) }); if (!response.ok) { throw new Error(`Discord webhook failed: ${response.status}`); } } } exports.WebhookNotifier = WebhookNotifier; //# sourceMappingURL=webhook-notifier.js.map