The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"updatedAt": "2026-03-10T02:01:45.000Z",
"createdAt": "2026-03-08T01:43:05.603Z",
"id": "YOUR_WORKFLOW_ID",
"name": "Wazuh SOAR \u2014 Alert Triage & Routing",
"description": null,
"active": true,
"isArchived": false,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "wazuh-alerts",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-208,
304
],
"id": "webhook-wazuh",
"name": "Wazuh Webhook"
},
{
"parameters": {
"jsCode": "const WINDOW_MS = 90 * 1000;\nconst state = $getWorkflowStaticData('global');\nif (!state.recent) state.recent = {};\nconst now = Date.now();\n\nconst out = [];\nfor (const item of items) {\n const body = item.json?.body || {};\n const ruleId = String(body?.rule?.id || 'unknown');\n const src = String(body?.srcip || body?.data?.srcip || 'unknown');\n const key = `${ruleId}|${src}`;\n const last = Number(state.recent[key] || 0);\n\n if (now - last >= WINDOW_MS) {\n state.recent[key] = now;\n out.push(item);\n }\n}\n\nfor (const k of Object.keys(state.recent)) {\n if (now - Number(state.recent[k]) > (6 * WINDOW_MS)) delete state.recent[k];\n}\n\nreturn out;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-16,
320
],
"id": "dedup-burst-window",
"name": "Dedup Burst Window"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "crit",
"leftValue": "={{ $json.body.rule.level }}",
"rightValue": 12,
"operator": {
"type": "number",
"operation": "gte"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Critical (12+)"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "high",
"leftValue": "={{ $json.body.rule.level }}",
"rightValue": 10,
"operator": {
"type": "number",
"operation": "gte"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "High (10-11)"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "med",
"leftValue": "={{ $json.body.rule.level }}",
"rightValue": 7,
"operator": {
"type": "number",
"operation": "gte"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Medium (7-9)"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
288,
304
],
"id": "switch-severity",
"name": "Severity Router"
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udea8 CRITICAL \u2014 Wazuh Rule {{ $json.body.rule.id }} (Level {{ $json.body.rule.level }})",
"description": "={{ $json.body.rule.description }}",
"color": 15158332,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity Level",
"value": "=Level **{{ $json.body.rule.level }}** \u2014 CRITICAL",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Agent",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83c\udfaf MITRE ATT&CK",
"value": "=Tactic: {{ ($json.body.rule.mitre?.tactic || []).join(', ') || 'N/A' }}\nTechnique: {{ ($json.body.rule.mitre?.technique || []).join(', ') || 'N/A' }}\nID: {{ ($json.body.rule.mitre?.id || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83c\udf10 Source IP",
"value": "={{ $json.body.srcip || $json.body.data?.srcip || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udc64 User",
"value": "={{ $json.body.data?.srcuser || $json.body.data?.dstuser || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udcc1 File / Path",
"value": "=`{{ $json.body.syscheck?.path || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udccd Location",
"value": "=`{{ $json.body.location || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 600) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
592,
112
],
"id": "discord-critical",
"name": "Discord \u2014 Critical",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udfe0 HIGH \u2014 Wazuh Rule {{ $json.body.rule.id }} (Level {{ $json.body.rule.level }})",
"description": "={{ $json.body.rule.description }}",
"color": 15105570,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity Level",
"value": "=Level **{{ $json.body.rule.level }}**",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Agent",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83c\udfaf MITRE ATT&CK",
"value": "=Tactic: {{ ($json.body.rule.mitre?.tactic || []).join(', ') || 'N/A' }}\nTechnique: {{ ($json.body.rule.mitre?.technique || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83c\udf10 Source IP",
"value": "={{ $json.body.srcip || $json.body.data?.srcip || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udc64 User",
"value": "={{ $json.body.data?.srcuser || $json.body.data?.dstuser || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udccd Location",
"value": "=`{{ $json.body.location || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 500) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
864,
400
],
"id": "discord-high",
"name": "Discord \u2014 High",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "ts",
"name": "timestamp",
"value": "={{ $json.body.timestamp }}",
"type": "string"
},
{
"id": "rid",
"name": "rule_id",
"value": "={{ $json.body.rule.id }}",
"type": "string"
},
{
"id": "lvl",
"name": "level",
"value": "={{ $json.body.rule.level }}",
"type": "number"
},
{
"id": "desc",
"name": "description",
"value": "={{ $json.body.rule.description }}",
"type": "string"
},
{
"id": "agent",
"name": "agent",
"value": "={{ $json.body.agent.name }}",
"type": "string"
},
{
"id": "src",
"name": "srcip",
"value": "={{ $json.body.srcip || '' }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
592,
512
],
"id": "set-medium",
"name": "Log Medium"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "ts",
"name": "timestamp",
"value": "={{ $json.body.timestamp }}",
"type": "string"
},
{
"id": "rid",
"name": "rule_id",
"value": "={{ $json.body.rule.id }}",
"type": "string"
},
{
"id": "lvl",
"name": "level",
"value": "={{ $json.body.rule.level }}",
"type": "number"
},
{
"id": "desc",
"name": "description",
"value": "={{ $json.body.rule.description }}",
"type": "string"
},
{
"id": "agent",
"name": "agent",
"value": "={{ $json.body.agent.name }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
592,
704
],
"id": "set-low",
"name": "Log Low"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "brute",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "authentication_fail",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"renameOutput": true,
"outputKey": "Brute Force"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "fim",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "syscheck",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"renameOutput": true,
"outputKey": "File Integrity"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "vuln",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "vulnerability-detector",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"renameOutput": true,
"outputKey": "Vulnerability"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
864,
112
],
"id": "switch-category",
"name": "Attack Categorizer"
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udd10 Brute Force Detected \u2014 {{ $json.body.agent?.name || 'unknown' }}",
"description": "={{ $json.body.rule.description }}",
"color": 15548997,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity",
"value": "=Level **{{ $json.body.rule.level }}** \u2014 {{ $json.body.rule.level >= 12 ? 'CRITICAL' : 'HIGH' }}",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Target Host",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83c\udf10 Attacker IP",
"value": "=`{{ $json.body.srcip || $json.body.data?.srcip || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udc64 Target User",
"value": "={{ $json.body.data?.srcuser || $json.body.data?.dstuser || 'N/A' }}",
"inline": true
},
{
"name": "\ud83c\udfaf MITRE ATT&CK",
"value": "=Tactic: {{ ($json.body.rule.mitre?.tactic || []).join(', ') || 'Credential Access' }}\nTechnique: {{ ($json.body.rule.mitre?.technique || []).join(', ') || 'Brute Force' }}\nID: {{ ($json.body.rule.mitre?.id || []).join(', ') || 'T1110' }}",
"inline": false
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udccd Log Source",
"value": "=`{{ $json.body.location || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udee1\ufe0f Recommended Action",
"value": "=\u2022 Check auth logs for repeat attempts\n\u2022 Consider blocking source IP at firewall\n\u2022 Review account lockout policies\n\u2022 Check for successful logins from this IP",
"inline": false
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 400) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1152,
0
],
"id": "discord-brute",
"name": "Discord \u2014 Brute Force",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const WINDOW_MS = 3 * 60 * 1000;\nconst state = $getWorkflowStaticData('global');\nif (!state.auth_recent_critical) state.auth_recent_critical = {};\nconst now = Date.now();\n\nconst out = [];\nfor (const item of items) {\n const body = item.json?.body || {};\n const src = String(body?.srcip || body?.data?.srcip || 'unknown');\n const user = String(body?.data?.srcuser || body?.data?.dstuser || 'unknown');\n const ruleId = String(body?.rule?.id || 'unknown');\n const key = `${src}|${user}|${ruleId}`;\n const last = Number(state.auth_recent_critical[key] || 0);\n\n if (now - last >= WINDOW_MS) {\n state.auth_recent_critical[key] = now;\n out.push(item);\n }\n}\n\nfor (const k of Object.keys(state.auth_recent_critical)) {\n if (now - Number(state.auth_recent_critical[k]) > (6 * WINDOW_MS)) delete state.auth_recent_critical[k];\n}\n\nreturn out;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1024,
0
],
"id": "dedup-auth-critical",
"name": "Dedup Auth Critical"
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udcc1 File Integrity Change \u2014 {{ $json.body.agent?.name || 'unknown' }}",
"description": "={{ $json.body.rule.description }}",
"color": 3447003,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity",
"value": "=Level **{{ $json.body.rule.level }}**",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Agent",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83d\udcc2 File Path",
"value": "=`{{ $json.body.syscheck?.path || 'N/A' }}`",
"inline": false
},
{
"name": "\ud83d\udd04 Event Type",
"value": "={{ $json.body.syscheck?.event || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udc64 Owner (After)",
"value": "={{ $json.body.syscheck?.uname_after || 'N/A' }}:{{ $json.body.syscheck?.gname_after || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udd12 Permissions (After)",
"value": "=`{{ $json.body.syscheck?.perm_after || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udd11 SHA256 Hash",
"value": "=`{{ ($json.body.syscheck?.sha256_after || 'N/A').slice(0, 20) }}...`",
"inline": true
},
{
"name": "\ud83d\udccf Size Change",
"value": "={{ $json.body.syscheck?.size_before || '?' }} \u2192 {{ $json.body.syscheck?.size_after || '?' }} bytes",
"inline": true
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udccd Location",
"value": "=`{{ $json.body.location || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 400) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1152,
208
],
"id": "discord-fim",
"name": "Discord \u2014 FIM Alert",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udee1\ufe0f Vulnerability Found \u2014 {{ $json.body.agent?.name || 'unknown' }}",
"description": "={{ $json.body.rule.description }}",
"color": 10038562,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity",
"value": "=Level **{{ $json.body.rule.level }}**",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Agent",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83d\udc1b CVE",
"value": "={{ $json.body.data?.vulnerability?.cve || $json.body.data?.cve || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udce6 Package",
"value": "={{ $json.body.data?.vulnerability?.package?.name || 'N/A' }} {{ $json.body.data?.vulnerability?.package?.version || '' }}",
"inline": true
},
{
"name": "\ud83d\udd34 CVSS Score",
"value": "={{ $json.body.data?.vulnerability?.severity || $json.body.data?.vulnerability?.cvss?.score || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udc8a Fix Available",
"value": "={{ $json.body.data?.vulnerability?.package?.fix_version || $json.body.data?.vulnerability?.status || 'Check vendor advisory' }}",
"inline": true
},
{
"name": "\ud83c\udfaf MITRE ATT&CK",
"value": "=Tactic: {{ ($json.body.rule.mitre?.tactic || []).join(', ') || 'N/A' }}\nTechnique: {{ ($json.body.rule.mitre?.technique || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udd17 Reference",
"value": "={{ ($json.body.data?.vulnerability?.references || []).slice(0, 2).join('\\n') || $json.body.data?.vulnerability?.reference || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 400) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1152,
400
],
"id": "discord-vuln",
"name": "Discord \u2014 Vulnerability",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "pf-internal-group",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "pfsense",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "pf-internal-ip",
"leftValue": "={{ (() => { const ip = $json.body.srcip || $json.body.data?.srcip || ''; return (ip.startsWith('192.168.') || ip.startsWith('10.') || ip.startsWith('172.')) ? 'private' : 'public'; })() }}",
"rightValue": "private",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "pfSense Internal (log)"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "pf-external",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "pfsense",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "pf-not-192",
"leftValue": "={{ $json.body.srcip || $json.body.data?.srcip || '' }}",
"rightValue": "192.168.",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "pf-not-10",
"leftValue": "={{ $json.body.srcip || $json.body.data?.srcip || '' }}",
"rightValue": "10.",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "pf-not-172",
"leftValue": "={{ $json.body.srcip || $json.body.data?.srcip || '' }}",
"rightValue": "172.",
"operator": {
"type": "string",
"operation": "notContains"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "pfSense External (discord)"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "fim",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "syscheck",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"renameOutput": true,
"outputKey": "File Integrity"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "auth",
"leftValue": "={{ ($json.body.rule.groups || []).join(',') }}",
"rightValue": "authentication_fail",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"renameOutput": true,
"outputKey": "Auth Failure"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
592,
304
],
"id": "switch-high-type",
"name": "High Alert Router"
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udd25 pfSense \u2014 {{ $json.body.data?.action || 'block' }} from {{ $json.body.srcip || $json.body.data?.srcip || 'unknown' }}",
"description": "={{ $json.body.rule.description }}",
"color": 15844367,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity",
"value": "=Level **{{ $json.body.rule.level }}**",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83c\udf10 Source IP",
"value": "=`{{ $json.body.srcip || $json.body.data?.srcip || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83c\udfaf Dest IP",
"value": "=`{{ $json.body.data?.dstip || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udd0c Dest Port",
"value": "={{ $json.body.data?.dstport || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udce1 Protocol",
"value": "={{ $json.body.data?.protocol || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udeab Action",
"value": "=**{{ $json.body.data?.action || 'block' }}**",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Agent",
"value": "={{ $json.body.agent?.name || 'N/A' }}",
"inline": true
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83c\udff7\ufe0f Classification",
"value": "=Recon/scan or policy block",
"inline": false
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 500) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
864,
208
],
"id": "discord-pfsense",
"name": "Discord \u2014 pfSense",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"authentication": "webhook",
"operation": "sendLegacy",
"content": "",
"embeds": {
"values": [
{
"title": "=\ud83d\udd11 Auth Failure \u2014 {{ $json.body.agent?.name || 'unknown' }}",
"description": "={{ $json.body.rule.description }}",
"color": 16776960,
"timestamp": "={{ new Date().toISOString() }}",
"fields": [
{
"name": "\u26a0\ufe0f Severity",
"value": "=Level **{{ $json.body.rule.level }}**",
"inline": true
},
{
"name": "\ud83d\udcdc Rule ID",
"value": "=`{{ $json.body.rule.id }}`",
"inline": true
},
{
"name": "\ud83d\udda5\ufe0f Target Host",
"value": "={{ $json.body.agent?.name || 'N/A' }} (`{{ $json.body.agent?.ip || 'N/A' }}`)",
"inline": true
},
{
"name": "\ud83c\udf10 Source IP",
"value": "=`{{ $json.body.srcip || $json.body.data?.srcip || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udc64 Username",
"value": "={{ $json.body.data?.srcuser || $json.body.data?.dstuser || 'N/A' }}",
"inline": true
},
{
"name": "\ud83c\udfaf MITRE ATT&CK",
"value": "=Tactic: {{ ($json.body.rule.mitre?.tactic || []).join(', ') || 'N/A' }}\nTechnique: {{ ($json.body.rule.mitre?.technique || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udce6 Groups",
"value": "={{ ($json.body.rule.groups || []).join(', ') || 'N/A' }}",
"inline": false
},
{
"name": "\ud83d\udccd Log Source",
"value": "=`{{ $json.body.location || 'N/A' }}`",
"inline": true
},
{
"name": "\ud83d\udccb Raw Log",
"value": "=```{{ ($json.body.full_log || 'N/A').slice(0, 500) }}```",
"inline": false
}
]
}
]
}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1120,
592
],
"id": "discord-auth-high",
"name": "Discord \u2014 Auth Failure",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const WINDOW_MS = 2 * 60 * 1000;\nconst state = $getWorkflowStaticData('global');\nif (!state.auth_recent_high) state.auth_recent_high = {};\nconst now = Date.now();\n\nconst out = [];\nfor (const item of items) {\n const body = item.json?.body || {};\n const src = String(body?.srcip || body?.data?.srcip || 'unknown');\n const user = String(body?.data?.srcuser || body?.data?.dstuser || 'unknown');\n const ruleId = String(body?.rule?.id || 'unknown');\n const key = `${src}|${user}|${ruleId}`;\n const last = Number(state.auth_recent_high[key] || 0);\n\n if (now - last >= WINDOW_MS) {\n state.auth_recent_high[key] = now;\n out.push(item);\n }\n}\n\nfor (const k of Object.keys(state.auth_recent_high)) {\n if (now - Number(state.auth_recent_high[k]) > (6 * WINDOW_MS)) delete state.auth_recent_high[k];\n}\n\nreturn out;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
752,
512
],
"id": "dedup-auth-high",
"name": "Dedup Auth High"
}
],
"connections": {
"Wazuh Webhook": {
"main": [
[
{
"node": "Dedup Burst Window",
"type": "main",
"index": 0
}
]
]
},
"Dedup Burst Window": {
"main": [
[
{
"node": "Severity Router",
"type": "main",
"index": 0
}
]
]
},
"Severity Router": {
"main": [
[
{
"node": "Discord \u2014 Critical",
"type": "main",
"index": 0
}
],
[
{
"node": "High Alert Router",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Medium",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Low",
"type": "main",
"index": 0
}
]
]
},
"Discord \u2014 Critical": {
"main": [
[
{
"node": "Attack Categorizer",
"type": "main",
"index": 0
}
]
]
},
"Attack Categorizer": {
"main": [
[
{
"node": "Dedup Auth Critical",
"type": "main",
"index": 0
}
],
[
{
"node": "Discord \u2014 FIM Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Discord \u2014 Vulnerability",
"type": "main",
"index": 0
}
],
[]
]
},
"High Alert Router": {
"main": [
[
{
"node": "Log Medium",
"type": "main",
"index": 0
}
],
[
{
"node": "Discord \u2014 pfSense",
"type": "main",
"index": 0
}
],
[
{
"node": "Discord \u2014 FIM Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Dedup Auth High",
"type": "main",
"index": 0
}
],
[
{
"node": "Discord \u2014 High",
"type": "main",
"index": 0
}
]
]
},
"Dedup Auth Critical": {
"main": [
[
{
"node": "Discord \u2014 Brute Force",
"type": "main",
"index": 0
}
]
]
},
"Dedup Auth High": {
"main": [
[
{
"node": "Discord \u2014 Auth Failure",
"type": "main",
"index": 0
}
]
]
},
"Log Low": {
"main": [
[]
]
}
},
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false,
"callerPolicy": "workflowsFromSameOwner"
},
"staticData": null,
"meta": null,
"activeVersionId": "59e7d5d7-214b-437b-b014-09d5b185e2f1",
"versionCounter": 43,
"triggerCount": 1,
"tags": [],
"shared": [
{
"updatedAt": "2026-03-08T01:43:05.612Z",
"createdAt": "2026-03-08T01:43:05.612Z",
"role": "workflow:owner",
"workflowId": "69ZRy9pXLiPIf5d7",
"projectId": "kafEMdKKgLswaGCu",
"project": {
"updatedAt": "2026-03-05T23:55:16.170Z",
"createdAt": "2026-03-05T23:48:50.092Z",
"id": "kafEMdKKgLswaGCu",
"name": "Moshe Geek <chief@chiefgyk3d.com>",
"type": "personal",
"icon": null,
"description": null,
"creatorId": "850a1525-0d7b-4ff8-ae56-76e699c15b7c"
}
}
],
"versionMetadata": {
"name": null,
"description": null
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
discordWebhookApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Wazuh SOAR — Alert Triage & Routing. Uses discord. Webhook trigger; 16 nodes.
Source: https://github.com/ChiefGyk3D/siem-docker-stack/blob/cccbc66855fbf8bd26b6cc974b1cec6c282cfdd9/n8n/wazuh-alert-triage.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
MVP — ClickUp Webhook → Discord Alert. Uses discord. Webhook trigger; 12 nodes.
Automatically convert GitHub issues into analyzed Jira tickets with AI-powered severity detection, developer assignment, and instant team alerts.
This workflow is a production-ready Meta Ads Webhook dispatcher for the Ad Account object. It receives webhook deliveries from Meta, returns the required acknowledgement, routes events by , logs them
This n8n workflow template is designed to provide real-time alerts on new cryptocurrency exchange listings and delistings. It caters especially to crypto traders, investors, and enthusiasts who want t
🛡️ Jamf Policy Integrity Monitor