This workflow corresponds to n8n.io template #6037 — we link there as the canonical source.
This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.
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 →
{
"id": "xfusgVqUUXHnAXQx",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "\u2705Splunk Alert - IP Reputation Check",
"tags": [],
"nodes": [
{
"id": "4cca587e-f7f6-42d0-9df1-938f1fbad8d3",
"name": "VirusTotal IP reputation check",
"type": "n8n-nodes-base.httpRequest",
"position": [
-540,
460
],
"parameters": {
"": "",
"url": "=https://www.virustotal.com/api/v3/ip_addresses/{{ $json.ip_address }}\n",
"method": "GET",
"options": {},
"sendBody": false,
"sendQuery": false,
"curlImport": "",
"infoMessage": "",
"sendHeaders": false,
"authentication": "predefinedCredentialType",
"httpVariantWarning": "",
"nodeCredentialType": "virusTotalApi",
"provideSslCertificates": false
},
"credentials": {
"virusTotalApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"extendsCredential": "virusTotalApi"
},
{
"id": "9da62a29-8a41-4ab8-b04e-4bafdaac47fe",
"name": "IP summary display",
"type": "n8n-nodes-base.html",
"position": [
400,
320
],
"parameters": {
"html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Threat Intelligence Summary</title>\n <style>\n body {\n font-family: \"Segoe UI\", sans-serif;\n background-color: #121212;\n color: #f0f0f0;\n padding: 20px;\n }\n .container {\n display: flex;\n gap: 20px;\n flex-wrap: wrap;\n }\n .card {\n background-color: #1e1e1e;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);\n padding: 20px;\n width: 100%;\n max-width: 500px;\n border: 1px solid #333;\n }\n h1 {\n color: #00bfff;\n }\n h2 {\n margin-top: 0;\n color: #4fc3f7;\n }\n .section-title {\n font-weight: bold;\n margin-top: 15px;\n color: #90caf9;\n }\n .label {\n font-weight: bold;\n color: #c5e1a5;\n }\n ul {\n margin-top: 5px;\n padding-left: 20px;\n }\n li {\n margin-bottom: 4px;\n }\n .tag {\n background-color: #333;\n color: #c5cae9;\n border-radius: 5px;\n padding: 2px 6px;\n margin-right: 5px;\n display: inline-block;\n }\n a {\n color: #81d4fa;\n text-decoration: none;\n }\n a:hover {\n text-decoration: underline;\n }\n .status {\n margin-top: 10px;\n margin-bottom: 10px;\n font-weight: bold;\n padding: 8px 16px;\n border-radius: 8px;\n display: inline-block;\n }\n .safe {\n background-color: #2e7d32;\n color: #a5d6a7;\n }\n .suspicious {\n background-color: #c62828;\n color: #ffab91;\n }\n </style>\n</head>\n<body>\n <h1>IP Threat Summary</h1>\n <p><span class=\"label\">IP:</span> {{ $json.summary.VirusTotal.IP }}</p>\n \n <p><span class=\"label\">Description:</span> {{ $json.summary.VirusTotal.Description }}</p>\n \n <div class=\"status {{ $json.summary.Status === 'Safe' ? 'safe' : 'suspicious' }}\">\n {{ $json.summary.Status }}\n </div>\n\n <div class=\"container\">\n <!-- VirusTotal Section -->\n <div class=\"card\">\n <h2>VirusTotal</h2>\n <p><span class=\"label\">Reputation:</span> {{ $json.summary.VirusTotal.Reputation }}</p>\n <p><span class=\"label\">WHOIS:</span> {{ $json.summary.VirusTotal.Whois }}</p>\n <p><span class=\"label\">Tags:</span> {{ $json.summary.VirusTotal.Tags_HTML }}</p>\n <p class=\"section-title\">Analysis Stats</p>\n <ul>\n <li>Harmless: {{ $json.summary.VirusTotal.Harmless }}</li>\n <li>Malicious: {{ $json.summary.VirusTotal.Malicious }}</li>\n <li>Suspicious: {{ $json.summary.VirusTotal.Suspicious }}</li>\n <li>Undetected: {{ $json.summary.VirusTotal.Undetected }}</li>\n </ul>\n </div>\n\n <!-- AlienVault Section -->\n <div class=\"card\">\n <h2>AlienVault</h2>\n <p><span class=\"label\">Reputation:</span> {{ $json.summary.AlienVault.Reputation }}</p>\n <p><span class=\"label\">WHOIS:</span> \n <a href=\"{{ $json.summary.AlienVault.Whois }}\" target=\"_blank\">View WHOIS</a>\n </p>\n <p><span class=\"label\">Pulse Count:</span> {{ $json.summary.AlienVault.Pulse_Count }}</p>\n <p class=\"section-title\">Pulse Names</p>\n <div>\n {{ $json.summary.AlienVault.Pulse_Names.split(',').map(name => `<span class=\"tag\">${name.trim()}</span>`).join('') }}\n </div>\n </div>\n\n <p style=\"margin-top: 5px;\">Generated at: {{ $json.summary.Generated_At }}</p>\n </div>\n</body>\n</html>\n"
},
"typeVersion": 1.2
},
{
"id": "eb78ae05-e2fc-4027-9f35-93d60fa92513",
"name": "Extract IOCs",
"type": "n8n-nodes-base.code",
"position": [
-840,
600
],
"parameters": {
"jsCode": "const body = $input.first().json.body;\n\nconst ip = body?.result?.src_ip || 'No IP found';\nconst reason = body?.result?.reason || 'No reason found';\n\nreturn [\n {\n json: {\n ip_address: ip,\n description: reason\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "157e919e-0e53-4e44-867f-5455f443b4df",
"name": "AlienVault Lookup",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-540,
720
],
"parameters": {
"": "",
"url": "=https://otx.alienvault.com/api/v1/indicators/IPv4/{{ $json.ip_address }}",
"method": "GET",
"options": {},
"sendBody": false,
"sendQuery": false,
"curlImport": "",
"infoMessage": "",
"sendHeaders": false,
"authentication": "predefinedCredentialType",
"httpVariantWarning": "",
"nodeCredentialType": "alienVaultApi",
"provideSslCertificates": false
},
"credentials": {
"alienVaultApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"extendsCredential": "alienVaultApi"
},
{
"id": "8cbccd4b-fa7e-4f02-8f3b-fca1c0478592",
"name": "Merge Threat Data",
"type": "n8n-nodes-base.merge",
"position": [
-260,
600
],
"parameters": {
"numberInputs": 3
},
"typeVersion": 3.2,
"alwaysOutputData": false
},
{
"id": "246f6880-d0d7-4315-9a88-a2334cbaa336",
"name": "Process Intel Data",
"type": "n8n-nodes-base.code",
"position": [
-40,
600
],
"parameters": {
"jsCode": "let virustotal = null;\nlet alienvault = null;\nlet metadata = null;\n\nfor (const item of items) {\n if (item.json?.data?.attributes) {\n // Likely VirusTotal result\n virustotal = item.json;\n } else if (item.json?.pulse_info) {\n // Likely AlienVault result\n alienvault = item.json;\n } else if (item.json?.description) {\n // The Wazuh description or IP metadata\n metadata = item.json;\n }\n}\n\nreturn [{\n json: {\n virustotal,\n alienvault,\n description: metadata?.description || \"No description\",\n ip_address: metadata?.ip_address || virustotal?.data?.id || \"Unknown IP\"\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "1398b87a-d2e8-4328-8c6a-b36c4b2809ef",
"name": "Generate IP Summary",
"type": "n8n-nodes-base.code",
"position": [
180,
600
],
"parameters": {
"jsCode": "// Get merged input (single item array)\nconst data = items[0].json;\n\n// VirusTotal extraction\nconst vt = data.virustotal?.data?.attributes;\nconst vtTagsArray = vt?.tags || [];\n\nconst malicious = vt?.last_analysis_stats?.malicious || 0;\nconst suspicious = vt?.last_analysis_stats?.suspicious || 0;\n\nconst vtSummary = vt ? {\n IP: data.virustotal.data.id,\n Reputation: vt.reputation,\n Tags: vtTagsArray.join(', '),\n Tags_HTML: vtTagsArray.map(tag =>\n `<span class=\"tag\">${tag.trim()}</span>`\n ).join(''),\n Harmless: vt.last_analysis_stats?.harmless || 0,\n Malicious: malicious,\n Suspicious: suspicious,\n Undetected: vt.last_analysis_stats?.undetected || 0,\n Whois: vt.whois?.split(\"\\n\")[0] || \"No WHOIS info\",\n Description: data.description || \"No description\"\n} : {};\n\n// AlienVault extraction with fallback\nlet avSummary = {};\nlet isAlienVaultSuspicious = false;\n\nif (data.alienvault && data.alienvault.pulse_info) {\n const av = data.alienvault;\n const pulseNamesArray = (av?.pulse_info?.pulses || []).map(p => p.name);\n const pulseCount = av?.pulse_info?.count || 0;\n\n isAlienVaultSuspicious = pulseCount > 0;\n\n avSummary = {\n IP: av.indicator,\n Reputation: av.reputation,\n Whois: av.whois,\n Pulse_Count: pulseCount,\n Pulse_Names: pulseNamesArray.join(', '),\n Pulse_Names_HTML: pulseNamesArray.map(name =>\n `<span class=\"tag\">${name.trim()}</span>`\n ).join('')\n };\n} else {\n avSummary = {\n IP: 'N/A (Private IP)',\n Reputation: 'N/A',\n Whois: 'N/A',\n Pulse_Count: 0,\n Pulse_Names: 'N/A',\n Pulse_Names_HTML: ''\n };\n}\n\n// Global Status Logic\nconst isVirusTotalSuspicious = malicious > 0 || suspicious > 0;\nconst finalStatus = (isVirusTotalSuspicious || isAlienVaultSuspicious) ? 'Suspicious' : 'Safe';\n\n// Timestamp\nconst generatedAt = new Intl.DateTimeFormat('en-IN', {\n dateStyle: 'short',\n timeStyle: 'medium',\n timeZone: 'Asia/Kolkata'\n}).format(new Date());\n\n// Final Output\nreturn [\n {\n json: {\n summary: {\n VirusTotal: vtSummary,\n AlienVault: avSummary,\n Status: finalStatus,\n Generated_At: generatedAt\n }\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "d3c233f3-663f-452a-9757-c114bc5ed7f7",
"name": "Filter Suspicious IPs",
"type": "n8n-nodes-base.switch",
"position": [
420,
880
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "559feb80-bac9-4300-82ac-7fbec9c24320",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.summary.Status }}",
"rightValue": "Suspicious"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "cdf4d022-a819-4dcf-a320-2c29f1eb204e",
"name": "Create IP Incident",
"type": "n8n-nodes-base.serviceNow",
"position": [
640,
760
],
"parameters": {
"resource": "incident",
"operation": "create",
"authentication": "basicAuth",
"additionalFields": {},
"short_description": "=IP: {{ $json.summary.VirusTotal.IP }} \n{{ $json.summary.VirusTotal.Description }}"
},
"credentials": {
"serviceNowBasicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "7aa90c7f-4766-4a7b-9e70-09ad884901e4",
"name": "Slack IP Alert",
"type": "n8n-nodes-base.slack",
"position": [
640,
980
],
"parameters": {
"text": "={{ $json.summary.VirusTotal.Status === 'Safe' ? '\u2705' : '\ud83d\udea8' }} IP {{ $json.summary.VirusTotal.IP }}\nStatus: *{{ $json.summary.Status }}*\nEvent: {{ $json.summary.VirusTotal.Description }}\n",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0913JPTZBJ",
"cachedResultName": "n8n-trigger"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.3
},
{
"id": "4d08d7c7-6fff-4688-b38d-3199c0ba733b",
"name": "Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
640,
320
],
"parameters": {
"sendTo": "user@example.com",
"message": "={{ $json.html }}",
"options": {},
"subject": "[New Alert] IP Reputation Check Summary"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "fe07061e-9ea1-405c-a6e3-41a07a8caada",
"name": "Splunk Alert",
"type": "n8n-nodes-base.webhook",
"position": [
-1080,
600
],
"parameters": {
"path": "e645d98e-f80c-47e5-b96e-762c96f3db76",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "e42e348c-52ae-46e9-80bc-a025ea9d4a1f",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1080,
400
],
"parameters": {
"width": 340,
"height": 180,
"content": "## \ud83d\udce5 Alert Ingestion & IOC Extraction\n- Receives alert from Splunk with IP address.\n- Extracts source IP and event reason.\n- Sends it to VirusTotal, AlienVault, and Merge nodes.\n"
},
"typeVersion": 1
},
{
"id": "011fc6c0-27cd-472c-9423-a4d1fc1194c9",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
400
],
"parameters": {
"color": 3,
"width": 600,
"height": 140,
"content": "## \ud83e\uddea Threat Enrichment & Summary Generation\n- Queries VirusTotal and AlienVault for reputation.\n- Merges data, tags, WHOIS, and pulse info.\n- Creates a readable summary of threat posture.\n"
},
"typeVersion": 1
},
{
"id": "65c83639-4dc3-473d-bd03-5b335db8c9c8",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
500
],
"parameters": {
"width": 340,
"height": 200,
"content": "## \ud83d\udea8 Alert Routing & Analyst Notification\n- If IP is marked suspicious:\n - Sends Slack alert\n - Creates an incident ticket\n- Emails an HTML summary report to the SOC inbox.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "3b5315c6-249b-47e2-b7bf-fddcf817eb77",
"connections": {
"Extract IOCs": {
"main": [
[
{
"node": "VirusTotal IP reputation check",
"type": "main",
"index": 0
},
{
"node": "AlienVault Lookup",
"type": "main",
"index": 0
},
{
"node": "Merge Threat Data",
"type": "main",
"index": 1
}
]
]
},
"Splunk Alert": {
"main": [
[
{
"node": "Extract IOCs",
"type": "main",
"index": 0
}
]
]
},
"AlienVault Lookup": {
"main": [
[
{
"node": "Merge Threat Data",
"type": "main",
"index": 2
}
]
]
},
"Merge Threat Data": {
"main": [
[
{
"node": "Process Intel Data",
"type": "main",
"index": 0
}
]
]
},
"IP summary display": {
"main": [
[
{
"node": "Gmail",
"type": "main",
"index": 0
}
]
]
},
"Process Intel Data": {
"main": [
[
{
"node": "Generate IP Summary",
"type": "main",
"index": 0
}
]
]
},
"Generate IP Summary": {
"main": [
[
{
"node": "IP summary display",
"type": "main",
"index": 0
},
{
"node": "Filter Suspicious IPs",
"type": "main",
"index": 0
}
]
]
},
"Filter Suspicious IPs": {
"main": [
[
{
"node": "Create IP Incident",
"type": "main",
"index": 0
},
{
"node": "Slack IP Alert",
"type": "main",
"index": 0
}
]
]
},
"VirusTotal IP reputation check": {
"main": [
[
{
"node": "Merge Threat Data",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
alienVaultApigmailOAuth2serviceNowBasicApislackOAuth2ApivirusTotalApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automates IP reputation analysis using Splunk alerts, enriches data via VirusTotal and AlienVault OTX, and generates actionable threat summaries for SOC teams — all without any coding.
Source: https://n8n.io/workflows/6037/ — 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.
This workflow helps SOC teams automate the detection and reporting of potentially malicious files using Wazuh alerts, VirusTotal hash validation, and integrated summary/report generation. It's ideal f
Suspicious_login_detection. Uses postgres, httpRequest, noOp, html. Webhook trigger; 43 nodes.
This n8n workflow is designed for security monitoring and incident response when suspicious login events are detected. It can be initiated either manually from within the n8n UI for testing or automat
Receive inventory movements via webhook, validate data, update stock levels, and trigger automatic alerts when products need reordering.
Wait. Uses httpRequest, itemLists, slack, gmail. Webhook trigger; 29 nodes.