This workflow corresponds to n8n.io template #10587 — we link there as the canonical source.
This workflow follows the Agent → Google Sheets 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": "fly1MRCiQdxRyuIZ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Cybersecurity Incident Response Automation",
"tags": [],
"nodes": [
{
"id": "87291e5f-c3d5-466a-83a1-de7a7213833c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-336,
0
],
"parameters": {
"width": 876,
"height": 1220,
"content": "## Cybersecurity Incident Response Automation with Claude AI\n\nThis workflow automates end-to-end cybersecurity incident response by ingesting alerts from multiple sources, enriching threat intelligence, assessing severity with Claude AI, executing containment actions, notifying stakeholders, and creating audit-ready tickets.\n\n### How it works\n\n1. **Ingest Alert** - Webhook receives alerts from SIEM, EDR, firewall, IDS/IPS\n2. **Validate & Normalize** - Standardizes alert format across all sources\n3. **Enrich Threat Intel** - Queries VirusTotal, AbuseIPDB, Shodan for context\n4. **AI Severity Assessment** - Claude AI classifies severity and recommends response\n5. **Containment Actions** - Auto-blocks IPs, isolates hosts, revokes tokens based on severity\n6. **Notify Stakeholders** - Alerts SOC team via Slack/email based on severity level\n7. **Create Incident Ticket** - Logs to Jira/ServiceNow with full enrichment data\n8. **Audit Log** - Writes compliance-ready record to Google Sheets\n\n### Setup Steps\n\n1. Import workflow into n8n\n2. Configure credentials:\n - **Webhook** - Point your SIEM/EDR to the webhook URL\n - **Anthropic API** - Claude AI for severity classification\n - **VirusTotal API** - Threat intelligence enrichment\n - **AbuseIPDB API** - IP reputation checking\n - **Slack OAuth** - SOC team notifications\n - **Jira API** - Incident ticket creation\n - **Google Sheets** - Compliance audit log\n3. Update firewall/EDR API endpoints in containment nodes\n4. Set your Slack channel IDs and Jira project key\n5. Activate the workflow\n\n### Sample Alert Payload\n```json\n{\n \"source\": \"splunk\",\n \"alertType\": \"brute_force\",\n \"sourceIP\": \"192.168.1.100\",\n \"destinationIP\": \"10.0.0.5\",\n \"affectedHost\": \"prod-server-01\",\n \"affectedUser\": \"admin@company.com\",\n \"timestamp\": \"2025-02-22T10:30:00Z\",\n \"rawLog\": \"Failed login attempt x50 in 60s\"\n}\n```\n\n### Features\n- **Multi-source ingestion** - SIEM, EDR, firewall, IDS/IPS\n- **Real-time threat enrichment** from VirusTotal & AbuseIPDB\n- **AI-powered severity scoring** with recommended playbooks\n- **Automated containment** for Critical/High severity\n- **Compliance audit trail** with full chain of custody"
},
"typeVersion": 1
},
{
"id": "3c5bc9a7-7d64-4b00-bcf6-8e3d79486bbf",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
672,
512
],
"parameters": {
"color": 4,
"width": 440,
"height": 328,
"content": "## 1. Alert Ingestion & Normalization"
},
"typeVersion": 1
},
{
"id": "4e96588f-1344-466f-a9b2-7f13ae0a402a",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1210,
340
],
"parameters": {
"color": 4,
"width": 716,
"height": 684,
"content": "## 2. Threat Intelligence Enrichment"
},
"typeVersion": 1
},
{
"id": "49feca99-89fb-470c-8014-883e4abdc3f1",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1944,
548
],
"parameters": {
"color": 4,
"width": 720,
"height": 284,
"content": "## 3. AI Severity Assessment & Playbook"
},
"typeVersion": 1
},
{
"id": "3dfedbe3-e986-4b82-8b6a-5fb23b748565",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2688,
272
],
"parameters": {
"color": 4,
"width": 1332,
"height": 828,
"content": "## 4. Containment, Notification & Ticketing"
},
"typeVersion": 1
},
{
"id": "a2161a2e-d428-453c-85c6-ce19d8b30491",
"name": "Receive Security Alert",
"type": "n8n-nodes-base.webhook",
"position": [
720,
672
],
"parameters": {
"path": "security-alert",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "9f3a37eb-6e55-493e-8197-c342e31468b1",
"name": "Normalize and Validate Alert",
"type": "n8n-nodes-base.code",
"position": [
944,
672
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Extract alert from request body\nconst raw = $input.item.json.body || $input.item.json;\n\n// Validate required fields\nconst required = ['source', 'alertType'];\nconst missing = required.filter(f => !raw[f]);\nif (missing.length > 0) {\n throw new Error(`Missing required alert fields: ${missing.join(', ')}`);\n}\n\n// Normalize alert type to standard taxonomy\nconst alertTypeMappings = {\n 'brute_force': 'BRUTE_FORCE',\n 'bruteforce': 'BRUTE_FORCE',\n 'login_failure': 'BRUTE_FORCE',\n 'malware': 'MALWARE_DETECTED',\n 'malware_detected': 'MALWARE_DETECTED',\n 'ransomware': 'RANSOMWARE',\n 'phishing': 'PHISHING',\n 'data_exfiltration': 'DATA_EXFILTRATION',\n 'exfiltration': 'DATA_EXFILTRATION',\n 'lateral_movement': 'LATERAL_MOVEMENT',\n 'privilege_escalation': 'PRIVILEGE_ESCALATION',\n 'ddos': 'DDOS_ATTACK',\n 'dos': 'DDOS_ATTACK',\n 'sql_injection': 'WEB_ATTACK',\n 'xss': 'WEB_ATTACK',\n 'web_attack': 'WEB_ATTACK',\n 'c2': 'C2_COMMUNICATION',\n 'c2_communication': 'C2_COMMUNICATION',\n 'unauthorized_access': 'UNAUTHORIZED_ACCESS'\n};\n\nconst normalizedType = alertTypeMappings[raw.alertType?.toLowerCase()] || raw.alertType?.toUpperCase() || 'UNKNOWN';\n\n// Normalize source\nconst sourceMap = {\n 'splunk': 'SIEM',\n 'qradar': 'SIEM',\n 'sentinel': 'SIEM',\n 'crowdstrike': 'EDR',\n 'sentinelone': 'EDR',\n 'defender': 'EDR',\n 'paloalto': 'FIREWALL',\n 'fortinet': 'FIREWALL',\n 'cisco': 'FIREWALL',\n 'snort': 'IDS',\n 'suricata': 'IDS'\n};\n\nconst sourceCategory = sourceMap[raw.source?.toLowerCase()] || 'UNKNOWN';\n\n// Extract IPs safely\nconst sourceIP = raw.sourceIP || raw.src_ip || raw.attackerIP || null;\nconst destinationIP = raw.destinationIP || raw.dst_ip || raw.targetIP || null;\n\n// Build normalized incident\nconst incident = {\n incidentId: `INC-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n alertType: normalizedType,\n source: raw.source || 'unknown',\n sourceCategory,\n sourceIP,\n destinationIP,\n affectedHost: raw.affectedHost || raw.hostname || raw.host || null,\n affectedUser: raw.affectedUser || raw.username || raw.user || null,\n affectedAsset: raw.affectedAsset || raw.asset || null,\n rawLog: raw.rawLog || raw.message || raw.log || JSON.stringify(raw),\n originalTimestamp: raw.timestamp || new Date().toISOString(),\n receivedAt: new Date().toISOString(),\n tags: raw.tags || [],\n additionalContext: raw.context || {}\n};\n\nreturn { json: { incident } };"
},
"typeVersion": 2
},
{
"id": "6e41f17e-d016-4a38-8199-589e37406213",
"name": "Check IP on VirusTotal",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
480
],
"parameters": {
"url": "=https://www.virustotal.com/api/v3/ip_addresses/{{ $json.incident.sourceIP || '8.8.8.8' }}",
"options": {
"timeout": 10000
},
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "x-apikey",
"value": "={{ $credentials.apiKey }}"
}
]
},
"nodeCredentialType": "virusTotalApi"
},
"credentials": {
"virusTotalApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "ac6cfdc6-3b7a-447f-aa04-5e1e9d6bac16",
"name": "Check IP on AbuseIPDB",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
672
],
"parameters": {
"url": "https://api.abuseipdb.com/api/v2/check",
"options": {
"timeout": 10000
},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "ipAddress",
"value": "={{ $('Normalize and Validate Alert').item.json.incident.sourceIP || '8.8.8.8' }}"
},
{
"name": "maxAgeInDays",
"value": "90"
},
{
"name": "verbose",
"value": "true"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Key",
"value": "={{ $credentials.apiKey }}"
},
{
"name": "Accept",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "055e3563-d369-4b85-b7a2-98027840115b",
"name": "Lookup Host on Shodan",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
864
],
"parameters": {
"url": "=https://api.shodan.io/shodan/host/{{ $('Normalize and Validate Alert').item.json.incident.sourceIP || '8.8.8.8' }}",
"options": {
"timeout": 10000
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "key",
"value": "YOUR_SHODAN_API_KEY"
}
]
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "30a307db-3d80-4ba5-8759-af013c51b534",
"name": "Merge Threat Intelligence",
"type": "n8n-nodes-base.merge",
"position": [
1520,
672
],
"parameters": {
"mode": "mergeByPosition"
},
"typeVersion": 3
},
{
"id": "e933942f-8e6b-440b-9adf-0fb70634bf4a",
"name": "Combine Enrichment Data",
"type": "n8n-nodes-base.code",
"position": [
1744,
672
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Pull all enrichment sources\nconst incident = $('Normalize and Validate Alert').item.json.incident;\nconst vtResponse = $('Check IP on VirusTotal').item.json;\nconst abuseResponse = $('Check IP on AbuseIPDB').item.json;\nconst shodanResponse = $('Lookup Host on Shodan').item.json;\n\n// Parse VirusTotal\nlet virusTotalData = { maliciousVotes: 0, suspiciousVotes: 0, harmlessVotes: 0, totalEngines: 0, country: 'Unknown', asOwner: 'Unknown' };\ntry {\n if (vtResponse && vtResponse.data?.attributes) {\n const attrs = vtResponse.data.attributes;\n const stats = attrs.last_analysis_stats || {};\n virusTotalData = {\n maliciousVotes: stats.malicious || 0,\n suspiciousVotes: stats.suspicious || 0,\n harmlessVotes: stats.harmless || 0,\n totalEngines: (stats.malicious || 0) + (stats.suspicious || 0) + (stats.harmless || 0) + (stats.undetected || 0),\n country: attrs.country || 'Unknown',\n asOwner: attrs.as_owner || 'Unknown',\n reputation: attrs.reputation || 0,\n lastAnalysisDate: attrs.last_analysis_date ? new Date(attrs.last_analysis_date * 1000).toISOString() : null\n };\n }\n} catch (e) { console.log('VT parse error:', e.message); }\n\n// Parse AbuseIPDB\nlet abuseIPData = { abuseConfidenceScore: 0, totalReports: 0, isWhitelisted: false, isp: 'Unknown', usageType: 'Unknown', countryCode: 'Unknown' };\ntry {\n if (abuseResponse && abuseResponse.data) {\n const d = abuseResponse.data;\n abuseIPData = {\n abuseConfidenceScore: d.abuseConfidenceScore || 0,\n totalReports: d.totalReports || 0,\n isWhitelisted: d.isWhitelisted || false,\n isp: d.isp || 'Unknown',\n usageType: d.usageType || 'Unknown',\n countryCode: d.countryCode || 'Unknown',\n lastReportedAt: d.lastReportedAt || null\n };\n }\n} catch (e) { console.log('AbuseIPDB parse error:', e.message); }\n\n// Parse Shodan\nlet shodanData = { openPorts: [], vulns: [], hostnames: [], os: 'Unknown', org: 'Unknown' };\ntry {\n if (shodanResponse && !shodanResponse.error) {\n shodanData = {\n openPorts: shodanResponse.ports || [],\n vulns: Object.keys(shodanResponse.vulns || {}),\n hostnames: shodanResponse.hostnames || [],\n os: shodanResponse.os || 'Unknown',\n org: shodanResponse.org || 'Unknown',\n isp: shodanResponse.isp || 'Unknown'\n };\n }\n} catch (e) { console.log('Shodan parse error:', e.message); }\n\n// Calculate composite threat score (0-100)\nconst vtScore = virusTotalData.totalEngines > 0\n ? Math.round((virusTotalData.maliciousVotes / virusTotalData.totalEngines) * 40)\n : 0;\nconst abuseScore = Math.round((abuseIPData.abuseConfidenceScore / 100) * 35);\nconst shodanScore = Math.min(shodanData.vulns.length * 5 + shodanData.openPorts.length * 0.5, 25);\nconst compositeThreatScore = Math.min(Math.round(vtScore + abuseScore + shodanScore), 100);\n\nreturn {\n json: {\n incident,\n threatIntelligence: {\n virusTotal: virusTotalData,\n abuseIPDB: abuseIPData,\n shodan: shodanData,\n compositeThreatScore,\n enrichedAt: new Date().toISOString()\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "44879567-ed26-40bd-bcde-f5d2b7d7e278",
"name": "Assess Severity with Claude AI",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1968,
672
],
"parameters": {
"text": "=You are an expert cybersecurity incident responder (CISSP, CISM certified). Analyze this security incident and provide a structured severity assessment with response playbook.\n\n**Incident Details:**\n- Incident ID: {{ $json.incident.incidentId }}\n- Alert Type: {{ $json.incident.alertType }}\n- Source: {{ $json.incident.source }} ({{ $json.incident.sourceCategory }})\n- Source IP: {{ $json.incident.sourceIP || 'N/A' }}\n- Destination IP: {{ $json.incident.destinationIP || 'N/A' }}\n- Affected Host: {{ $json.incident.affectedHost || 'N/A' }}\n- Affected User: {{ $json.incident.affectedUser || 'N/A' }}\n- Timestamp: {{ $json.incident.originalTimestamp }}\n- Raw Log: {{ $json.incident.rawLog }}\n\n**Threat Intelligence:**\n- VirusTotal Malicious Votes: {{ $json.threatIntelligence.virusTotal.maliciousVotes }} / {{ $json.threatIntelligence.virusTotal.totalEngines }} engines\n- AbuseIPDB Confidence Score: {{ $json.threatIntelligence.abuseIPDB.abuseConfidenceScore }}%\n- AbuseIPDB Total Reports: {{ $json.threatIntelligence.abuseIPDB.totalReports }}\n- Source IP Country: {{ $json.threatIntelligence.virusTotal.country }}\n- IP Owner/ISP: {{ $json.threatIntelligence.abuseIPDB.isp }}\n- Open Ports on Host: {{ JSON.stringify($json.threatIntelligence.shodan.openPorts) }}\n- Known Vulnerabilities: {{ JSON.stringify($json.threatIntelligence.shodan.vulns) }}\n- Composite Threat Score: {{ $json.threatIntelligence.compositeThreatScore }}/100\n\n**Assessment Guidelines:**\n- CRITICAL: Active breach, ransomware, data exfiltration, C2 confirmed \u2014 immediate containment\n- HIGH: Confirmed malicious activity, privilege escalation, lateral movement \u2014 rapid response\n- MEDIUM: Suspicious activity, multiple failed logins, known bad IP \u2014 investigate and monitor\n- LOW: Single anomaly, low-confidence detection, likely false positive \u2014 log and review\n\n**Response Format (JSON only, no markdown):**\n{\n \"severity\": \"CRITICAL | HIGH | MEDIUM | LOW\",\n \"severityScore\": 95,\n \"confidence\": \"HIGH | MEDIUM | LOW\",\n \"threatCategory\": \"brief category name\",\n \"summary\": \"2-3 sentence plain-English summary of the incident\",\n \"isFalsePositive\": false,\n \"falsePositiveReason\": null,\n \"immediateActions\": [\"ordered list of actions to take right now\"],\n \"containmentSteps\": [\"specific technical containment actions\"],\n \"investigationSteps\": [\"forensic investigation steps\"],\n \"affectedSystems\": [\"list of potentially affected systems/services\"],\n \"iocList\": [\"indicators of compromise to hunt for\"],\n \"mitreTactics\": [\"MITRE ATT&CK tactic names\"],\n \"mitreTechniques\": [\"MITRE ATT&CK technique IDs like T1110\"],\n \"recommendedPlaybook\": \"BRUTE_FORCE | MALWARE | RANSOMWARE | PHISHING | DATA_EXFIL | INSIDER_THREAT | WEB_ATTACK | GENERIC\",\n \"escalateToManagement\": true,\n \"requiresForensics\": false,\n \"estimatedImpact\": \"brief impact statement\"\n}",
"options": {
"systemMessage": "You are a cybersecurity incident response expert. Respond with JSON only \u2014 no markdown, no code blocks, no additional text. Your assessments must be accurate, actionable, and aligned with NIST IR framework and MITRE ATT&CK."
},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "587a614a-3619-48ee-9aff-be85263de995",
"name": "Claude AI Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
2040,
896
],
"parameters": {
"model": "=claude-sonnet-4-20250514",
"options": {
"temperature": 0.2
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "13b1ed17-d525-4cb3-8b00-19922a6eee68",
"name": "Parse AI Assessment",
"type": "n8n-nodes-base.code",
"position": [
2320,
672
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const aiResponse = $input.item.json;\nlet aiText = aiResponse.response || aiResponse.output || aiResponse.text || '';\n\n// Handle content array format from Anthropic\nif (aiResponse.content && Array.isArray(aiResponse.content)) {\n aiText = aiResponse.content[0]?.text || '';\n}\n\n// Strip markdown code blocks if present\nconst cleanText = aiText\n .replace(/```json\\s*/g, '')\n .replace(/```\\s*/g, '')\n .trim();\n\nlet assessment;\ntry {\n assessment = JSON.parse(cleanText);\n} catch (error) {\n throw new Error(`Failed to parse Claude AI response: ${error.message}. Raw: ${cleanText.substring(0, 200)}`);\n}\n\n// Pull enriched incident from upstream\nconst enrichedData = $('Combine Enrichment Data').item.json;\n\n// Determine auto-containment flag (Critical or High non-false-positive)\nconst autoContain = ['CRITICAL', 'HIGH'].includes(assessment.severity) && !assessment.isFalsePositive;\n\n// Determine notification level\nconst notifyLevel = {\n 'CRITICAL': 'P1_IMMEDIATE',\n 'HIGH': 'P2_URGENT',\n 'MEDIUM': 'P3_STANDARD',\n 'LOW': 'P4_INFORMATIONAL'\n}[assessment.severity] || 'P3_STANDARD';\n\nreturn {\n json: {\n incident: enrichedData.incident,\n threatIntelligence: enrichedData.threatIntelligence,\n assessment,\n responseDecision: {\n autoContain,\n notifyLevel,\n createTicket: true,\n requiresEscalation: assessment.escalateToManagement || assessment.severity === 'CRITICAL',\n requiresForensics: assessment.requiresForensics || false\n },\n assessedAt: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
},
{
"id": "42cd014f-9347-41db-8538-be5284179da6",
"name": "Check Severity for Auto-Containment",
"type": "n8n-nodes-base.if",
"position": [
2544,
672
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.responseDecision.autoContain }}"
}
]
}
},
"typeVersion": 2
},
{
"id": "0d4cfc9b-7215-4b30-917d-563c4b7e42c2",
"name": "Block Malicious IP on Firewall",
"type": "n8n-nodes-base.httpRequest",
"position": [
2768,
384
],
"parameters": {
"url": "https://YOUR_FIREWALL_API/api/v1/blocked-ips",
"method": "POST",
"options": {
"timeout": 10000
},
"jsonBody": "={\n \"ip\": \"{{ $json.incident.sourceIP }}\",\n \"reason\": \"Auto-blocked by IRT: {{ $json.incident.incidentId }} - {{ $json.assessment.severity }} {{ $json.incident.alertType }}\",\n \"duration\": \"{{ $json.assessment.severity === 'CRITICAL' ? 'permanent' : '24h' }}\",\n \"addedBy\": \"n8n-incident-response\",\n \"timestamp\": \"{{ new Date().toISOString() }}\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "b262e14b-1082-4436-bd03-44df626ca148",
"name": "Isolate Affected Host via EDR",
"type": "n8n-nodes-base.httpRequest",
"position": [
2768,
672
],
"parameters": {
"url": "https://YOUR_EDR_API/api/v1/devices/isolate",
"method": "POST",
"options": {
"timeout": 15000
},
"jsonBody": "={\n \"hostname\": \"{{ $json.incident.affectedHost }}\",\n \"incidentId\": \"{{ $json.incident.incidentId }}\",\n \"severity\": \"{{ $json.assessment.severity }}\",\n \"reason\": \"{{ $json.assessment.summary }}\",\n \"isolationType\": \"{{ $json.assessment.severity === 'CRITICAL' ? 'full' : 'network' }}\",\n \"isolatedBy\": \"n8n-incident-response\",\n \"timestamp\": \"{{ new Date().toISOString() }}\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "d23ef0a4-a970-4569-8794-deddbc19e571",
"name": "Revoke User Tokens and Sessions",
"type": "n8n-nodes-base.httpRequest",
"position": [
2768,
960
],
"parameters": {
"url": "https://YOUR_IDP_API/api/v1/users/revoke-sessions",
"method": "POST",
"options": {
"timeout": 10000
},
"jsonBody": "={\n \"userEmail\": \"{{ $json.incident.affectedUser }}\",\n \"incidentId\": \"{{ $json.incident.incidentId }}\",\n \"revokeAll\": true,\n \"reason\": \"Security incident: {{ $json.assessment.severity }} {{ $json.incident.alertType }}\",\n \"revokedBy\": \"n8n-incident-response\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "84aa8a76-5002-4bdb-8633-d0cfe9172329",
"name": "Notify SOC Team on Slack",
"type": "n8n-nodes-base.httpRequest",
"position": [
2992,
464
],
"parameters": {
"url": "https://slack.com/api/chat.postMessage",
"method": "POST",
"options": {
"timeout": 10000
},
"jsonBody": "={\n \"channel\": \"{{ $json.assessment.severity === 'CRITICAL' ? '#soc-critical' : $json.assessment.severity === 'HIGH' ? '#soc-alerts' : '#soc-monitoring' }}\",\n \"text\": \"\ud83d\udea8 *{{ $json.assessment.severity }} Security Incident Detected*\",\n \"blocks\": [\n {\n \"type\": \"header\",\n \"text\": {\n \"type\": \"plain_text\",\n \"text\": \"\ud83d\udea8 {{ $json.assessment.severity }} Incident: {{ $json.incident.alertType }}\"\n }\n },\n {\n \"type\": \"section\",\n \"fields\": [\n { \"type\": \"mrkdwn\", \"text\": \"*Incident ID:*\\n{{ $json.incident.incidentId }}\" },\n { \"type\": \"mrkdwn\", \"text\": \"*Severity:*\\n{{ $json.assessment.severity }} ({{ $json.assessment.severityScore }}/100)\" },\n { \"type\": \"mrkdwn\", \"text\": \"*Source IP:*\\n{{ $json.incident.sourceIP || 'N/A' }}\" },\n { \"type\": \"mrkdwn\", \"text\": \"*Affected Host:*\\n{{ $json.incident.affectedHost || 'N/A' }}\" },\n { \"type\": \"mrkdwn\", \"text\": \"*Alert Source:*\\n{{ $json.incident.source }}\" },\n { \"type\": \"mrkdwn\", \"text\": \"*Containment:*\\n{{ $json.responseDecision.autoContain ? '\u2705 Auto-contained' : '\u26a0\ufe0f Manual action required' }}\" }\n ]\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Summary:*\\n{{ $json.assessment.summary }}\"\n }\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*MITRE ATT&CK:* {{ $json.assessment.mitreTechniques.join(', ') }}\\n*Playbook:* {{ $json.assessment.recommendedPlaybook }}\"\n }\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "slackApi"
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "fed148a8-b3b9-4035-a4a3-f95d70973808",
"name": "Create Incident Ticket in Jira",
"type": "n8n-nodes-base.httpRequest",
"position": [
2992,
816
],
"parameters": {
"url": "https://YOUR_JIRA_DOMAIN.atlassian.net/rest/api/3/issue",
"method": "POST",
"options": {
"timeout": 15000
},
"jsonBody": "={\n \"fields\": {\n \"project\": { \"key\": \"SEC\" },\n \"issuetype\": { \"name\": \"Incident\" },\n \"summary\": \"[{{ $json.assessment.severity }}] {{ $json.incident.alertType }} - {{ $json.incident.incidentId }}\",\n \"priority\": { \"name\": \"{{ $json.assessment.severity === 'CRITICAL' ? 'Highest' : $json.assessment.severity === 'HIGH' ? 'High' : $json.assessment.severity === 'MEDIUM' ? 'Medium' : 'Low' }}\" },\n \"description\": {\n \"type\": \"doc\",\n \"version\": 1,\n \"content\": [\n {\n \"type\": \"paragraph\",\n \"content\": [{ \"type\": \"text\", \"text\": \"Incident ID: {{ $json.incident.incidentId }}\" }]\n },\n {\n \"type\": \"paragraph\",\n \"content\": [{ \"type\": \"text\", \"text\": \"Summary: {{ $json.assessment.summary }}\" }]\n },\n {\n \"type\": \"paragraph\",\n \"content\": [{ \"type\": \"text\", \"text\": \"Source IP: {{ $json.incident.sourceIP || 'N/A' }} | AbuseIPDB Score: {{ $json.threatIntelligence.abuseIPDB.abuseConfidenceScore }}%\" }]\n },\n {\n \"type\": \"paragraph\",\n \"content\": [{ \"type\": \"text\", \"text\": \"MITRE Techniques: {{ $json.assessment.mitreTechniques.join(', ') }}\" }]\n },\n {\n \"type\": \"paragraph\",\n \"content\": [{ \"type\": \"text\", \"text\": \"Playbook: {{ $json.assessment.recommendedPlaybook }}\" }]\n }\n ]\n },\n \"labels\": [\"security-incident\", \"{{ $json.incident.alertType.toLowerCase().replace(/_/g, '-') }}\", \"{{ $json.assessment.severity.toLowerCase() }}\"],\n \"customfield_10016\": \"{{ $json.incident.incidentId }}\"\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "jiraSoftwareCloudApi"
},
"credentials": {
"jiraSoftwareCloudApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "8c38991d-dd66-4350-935e-a62599d387b9",
"name": "Build Final Incident Report",
"type": "n8n-nodes-base.code",
"position": [
3216,
600
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $('Parse AI Assessment').item.json;\nconst slackResponse = $('Notify SOC Team on Slack').item.json;\nconst jiraResponse = $('Create Incident Ticket in Jira').item.json;\n\n// Extract Jira ticket key\nconst jiraTicketKey = jiraResponse?.key || jiraResponse?.id || 'TICKET_CREATION_FAILED';\nconst jiraTicketUrl = jiraResponse?.key\n ? `https://YOUR_JIRA_DOMAIN.atlassian.net/browse/${jiraResponse.key}`\n : null;\n\n// Containment summary\nconst containmentActions = [];\nif (data.responseDecision.autoContain) {\n if (data.incident.sourceIP) containmentActions.push('IP blocked on firewall');\n if (data.incident.affectedHost) containmentActions.push('Host isolated via EDR');\n if (data.incident.affectedUser) containmentActions.push('User sessions revoked');\n}\n\nconst report = {\n success: true,\n incidentId: data.incident.incidentId,\n severity: data.assessment.severity,\n severityScore: data.assessment.severityScore,\n confidence: data.assessment.confidence,\n alertType: data.incident.alertType,\n source: data.incident.source,\n summary: data.assessment.summary,\n affectedAssets: {\n host: data.incident.affectedHost,\n user: data.incident.affectedUser,\n sourceIP: data.incident.sourceIP,\n destinationIP: data.incident.destinationIP\n },\n threatIntelligence: {\n compositeThreatScore: data.threatIntelligence.compositeThreatScore,\n virusTotalMalicious: data.threatIntelligence.virusTotal.maliciousVotes,\n abuseConfidenceScore: data.threatIntelligence.abuseIPDB.abuseConfidenceScore,\n knownVulnerabilities: data.threatIntelligence.shodan.vulns\n },\n containment: {\n autoContainmentExecuted: data.responseDecision.autoContain,\n actionsExecuted: containmentActions\n },\n response: {\n jiraTicket: jiraTicketKey,\n jiraTicketUrl,\n slackNotified: !slackResponse?.error,\n notificationLevel: data.responseDecision.notifyLevel\n },\n playbook: data.assessment.recommendedPlaybook,\n mitreTechniques: data.assessment.mitreTechniques,\n iocList: data.assessment.iocList,\n immediateActions: data.assessment.immediateActions,\n investigationSteps: data.assessment.investigationSteps,\n escalateToManagement: data.responseDecision.requiresEscalation,\n requiresForensics: data.responseDecision.requiresForensics,\n processedAt: new Date().toISOString()\n};\n\nreturn { json: report };"
},
"typeVersion": 2
},
{
"id": "2a25c98d-62f1-4622-ac2a-49d13d24e7f4",
"name": "Write Compliance Audit Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
3440,
600
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "b1c1d7ae-abb6-43f1-a340-6f93f8223222",
"name": "Send Incident Response to Caller",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
3664,
600
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json, null, 2) }}"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "f722c8c5-0894-420a-9c28-2df92d606b75",
"connections": {
"Claude AI Model": {
"ai_languageModel": [
[
{
"node": "Assess Severity with Claude AI",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Parse AI Assessment": {
"main": [
[
{
"node": "Check Severity for Auto-Containment",
"type": "main",
"index": 0
}
]
]
},
"Check IP on AbuseIPDB": {
"main": [
[
{
"node": "Merge Threat Intelligence",
"type": "main",
"index": 1
}
]
]
},
"Lookup Host on Shodan": {
"main": [
[
{
"node": "Merge Threat Intelligence",
"type": "main",
"index": 1
}
]
]
},
"Check IP on VirusTotal": {
"main": [
[
{
"node": "Merge Threat Intelligence",
"type": "main",
"index": 0
}
]
]
},
"Receive Security Alert": {
"main": [
[
{
"node": "Normalize and Validate Alert",
"type": "main",
"index": 0
}
]
]
},
"Combine Enrichment Data": {
"main": [
[
{
"node": "Assess Severity with Claude AI",
"type": "main",
"index": 0
}
]
]
},
"Notify SOC Team on Slack": {
"main": [
[
{
"node": "Build Final Incident Report",
"type": "main",
"index": 0
}
]
]
},
"Merge Threat Intelligence": {
"main": [
[
{
"node": "Combine Enrichment Data",
"type": "main",
"index": 0
}
]
]
},
"Write Compliance Audit Log": {
"main": [
[
{
"node": "Send Incident Response to Caller",
"type": "main",
"index": 0
}
]
]
},
"Build Final Incident Report": {
"main": [
[
{
"node": "Write Compliance Audit Log",
"type": "main",
"index": 0
}
]
]
},
"Normalize and Validate Alert": {
"main": [
[
{
"node": "Check IP on VirusTotal",
"type": "main",
"index": 0
},
{
"node": "Check IP on AbuseIPDB",
"type": "main",
"index": 0
},
{
"node": "Lookup Host on Shodan",
"type": "main",
"index": 0
}
]
]
},
"Isolate Affected Host via EDR": {
"main": [
[
{
"node": "Create Incident Ticket in Jira",
"type": "main",
"index": 0
}
]
]
},
"Assess Severity with Claude AI": {
"main": [
[
{
"node": "Parse AI Assessment",
"type": "main",
"index": 0
}
]
]
},
"Block Malicious IP on Firewall": {
"main": [
[
{
"node": "Notify SOC Team on Slack",
"type": "main",
"index": 0
}
]
]
},
"Create Incident Ticket in Jira": {
"main": [
[
{
"node": "Build Final Incident Report",
"type": "main",
"index": 0
}
]
]
},
"Revoke User Tokens and Sessions": {
"main": [
[
{
"node": "Create Incident Ticket in Jira",
"type": "main",
"index": 0
}
]
]
},
"Check Severity for Auto-Containment": {
"main": [
[
{
"node": "Block Malicious IP on Firewall",
"type": "main",
"index": 0
},
{
"node": "Isolate Affected Host via EDR",
"type": "main",
"index": 0
},
{
"node": "Revoke User Tokens and Sessions",
"type": "main",
"index": 0
}
],
[
{
"node": "Notify SOC Team on Slack",
"type": "main",
"index": 0
},
{
"node": "Create Incident Ticket in Jira",
"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.
anthropicApigoogleSheetsOAuth2ApijiraSoftwareCloudApislackApivirusTotalApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automates end-to-end cybersecurity incident response by ingesting alerts from multiple sources, enriching threat intelligence, assessing severity with Claude AI, executing containment actions, notifying stakeholders, and creating audit-ready tickets. Ingest Alert -…
Source: https://n8n.io/workflows/10587/ — 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.
⏺ 🚀 How it works
Fully automates your service order pipeline from incoming booking to supplier confirmation — with built-in SLA enforcement and automatic escalation if a supplier goes silent. 📥 Receives orders via web
Tired of grinding out YouTube content? This n8n workflow turns AI into your personal video factory—creating engaging, faceless shorts on autopilot. Perfect for creators, marketers, or side-hustlers lo
Faceless YouTube Generator. Uses httpRequest, limit, googleDrive, googleSheets. Webhook trigger; 49 nodes.
This workflow turns your WhatsApp Business number into a 24/7 AI-powered customer assistant — without any third-party chatbot platform. It receives incoming WhatsApp messages via Evolution API, unders