iosif-castrucci-hub/n8n-Threat-Intelligence-Enrichment-Pipeline
GitHub: iosif-castrucci-hub/n8n-Threat-Intelligence-Enrichment-Pipeline
Stars: 1 | Forks: 0
# Threat Intelligence Enrichment Pipeline
A cybersecurity automation project built with **n8n**, **AbuseIPDB**, **VirusTotal**, **Google Sheets**, and **Telegram**.
This project demonstrates an advanced threat intelligence enrichment pipeline that receives an IOC, detects whether it is an IP address, URL, or domain, enriches it using threat intelligence APIs, calculates a risk score, saves the report in Google Sheets, and sends a Telegram alert when the indicator is classified as high risk.
## Project Overview
The goal of this project is to automate the enrichment and triage of Indicators of Compromise.
An IOC can be submitted through a Webhook in JSON format. The workflow automatically normalizes the indicator, detects its type, routes it to the correct enrichment branch, collects threat intelligence data, calculates a final risk score, logs the result, and sends an alert if needed.
Supported IOC types:
IP address
URL
Domain
Unsupported / Unknown IOC
This project is designed as a practical demo of **SOAR-style automation**, **threat intelligence enrichment**, **IOC classification**, **risk scoring**, and **security alerting**.
## Tech Stack
* **n8n Cloud** — workflow automation platform
* **Webhook Trigger** — receives IOC submissions
* **Code Nodes** — normalize indicators, process enrichment results, calculate risk
* **Switch Node** — routes indicators by type
* **HTTP Request Nodes** — call threat intelligence APIs
* **Wait Node** — waits for VirusTotal URL analysis
* **Google Sheets** — stores enrichment reports
* **IF Node** — checks if the IOC is high risk
* **Telegram Bot API** — sends high-risk threat intelligence alerts
* **AbuseIPDB API** — enriches IP addresses
* **VirusTotal API** — enriches IPs, URLs, and domains
## Main Features
### IOC Intake
The workflow starts with a Webhook that receives an IOC.
Example IP submission:
{
"indicator": "185.220.101.1",
"source": "Manual Investigation",
"caseId": "CASE-001",
"submittedBy": "analyst@example.com"
}
Example URL submission:
{
"indicator": "http://fake-login-security-example.com/verify",
"source": "Phishing Investigation",
"caseId": "CASE-002",
"submittedBy": "analyst@example.com"
}
Example domain submission:
{
"indicator": "example.com",
"source": "Domain Investigation",
"caseId": "CASE-003",
"submittedBy": "analyst@example.com"
}
### IOC Type Detection
The workflow detects whether the submitted indicator is:
ip
url
domain
unknown
This detection is handled by a Code node before the indicator is routed through the Switch node.
### Routing by IOC Type
The workflow uses a Switch node to route indicators into separate enrichment branches.
IP → AbuseIPDB + VirusTotal IP Report
URL → VirusTotal URL Analysis
Domain → VirusTotal Domain Report
Unknown → Logged as Unsupported
### IP Enrichment
IP indicators are enriched using:
AbuseIPDB IP Check
VirusTotal IP Report
Collected values include:
AbuseIPDB Score
AbuseIPDB Total Reports
Country
ISP
Usage Type
VirusTotal Malicious Detections
VirusTotal Suspicious Detections
VirusTotal Harmless Detections
VirusTotal Undetected Detections
### URL Enrichment
URL indicators are submitted to VirusTotal for analysis.
The workflow:
Submits URL to VirusTotal
Waits for the analysis
Retrieves the VirusTotal analysis result
Normalizes the enrichment output
Collected values include:
VirusTotal Analysis Status
VirusTotal Malicious Detections
VirusTotal Suspicious Detections
VirusTotal Harmless Detections
VirusTotal Undetected Detections
Extracted Domain
### Domain Enrichment
Domain indicators are enriched using the VirusTotal Domain Report endpoint.
Collected values include:
VirusTotal Malicious Detections
VirusTotal Suspicious Detections
VirusTotal Harmless Detections
VirusTotal Undetected Detections
VirusTotal Domain Reputation
VirusTotal Categories
### Unsupported IOC Handling
If the submitted indicator is not a valid IP address, URL, or domain, the workflow does not fail.
Instead, it logs the indicator as:
Indicator Type = unknown
Status = Unsupported
Risk Level = Unsupported
This keeps the workflow stable and provides traceability for invalid submissions.
### Risk Score Calculation
The workflow calculates a final risk score from `0` to `100`.
Risk factors include:
AbuseIPDB score
VirusTotal malicious detections
VirusTotal suspicious detections
Indicator type
VirusTotal URL analysis status
Negative domain reputation
Example scoring logic:
High AbuseIPDB score → adds risk
VirusTotal malicious detections → adds risk
VirusTotal suspicious detections → adds risk
URL indicator submitted → adds contextual risk
Domain indicator submitted → adds contextual risk
Negative domain reputation → adds risk
### Risk Level Classification
The workflow classifies the final score as:
0 - 34 Low
35 - 64 Medium
65 - 84 High
85 - 100 Critical
### Google Sheets Reporting
Every supported IOC enrichment is saved in Google Sheets.
Unsupported IOCs are also logged.
Google Sheets acts as a lightweight threat intelligence case log.
Stored fields include:
Report ID
Timestamp
Case ID
Submitted By
Source
Indicator
Indicator Type
AbuseIPDB Score
VT Malicious
VT Suspicious
VT Harmless
VT Undetected
Risk Score
Risk Level
Recommendation
Action Taken
Status
Notes
### Telegram Alerting
If an IOC is classified as **High** or **Critical**, the workflow sends a Telegram alert.
Example alert:
🚨 Threat Intelligence Alert
Risk Level: High
Risk Score: 90/100
Indicator: 185.220.101.1
Type: ip
Case ID: CASE-001
Source: Manual Investigation
Submitted By: analyst@example.com
AbuseIPDB Score: 100
VirusTotal:
Malicious: 12
Suspicious: 3
Harmless: 50
Undetected: 20
Recommendation:
Block or monitor the indicator, review related logs, and check for connections from internal assets.
Status: Open
After sending the Telegram alert, the workflow updates the Google Sheet row:
Action Taken = Telegram alert sent
Status = Notified
## Workflow Structure
The advanced version contains 16 nodes.
01 Webhook - Receive IOC
02 Code - Normalize and Detect IOC Type
03 Switch - Route by IOC Type
IP Branch:
04A HTTP Request - AbuseIPDB IP Check
05A HTTP Request - VirusTotal IP Report
06A Code - Normalize IP Enrichment
URL Branch:
04B HTTP Request - Submit URL to VirusTotal
05B Wait - Wait for URL Analysis
06B HTTP Request - Get URL Analysis
07B Code - Normalize URL Enrichment
Domain Branch:
04C HTTP Request - VirusTotal Domain Report
05C Code - Normalize Domain Enrichment
Unsupported Branch:
04D Google Sheets - Save Unsupported IOC
Common Branch:
08 Code - Calculate Threat Risk Score
09 Google Sheets - Save Threat Intel Report
10 IF - High Risk Indicator?
11 Telegram - Send Threat Intel Alert
12 Google Sheets - Update Action Taken
## Workflow Flow
01 Webhook - Receive IOC
↓
02 Code - Normalize and Detect IOC Type
↓
03 Switch - Route by IOC Type
├── IP
│ ↓
│ 04A HTTP Request - AbuseIPDB IP Check
│ ↓
│ 05A HTTP Request - VirusTotal IP Report
│ ↓
│ 06A Code - Normalize IP Enrichment
│
├── URL
│ ↓
│ 04B HTTP Request - Submit URL to VirusTotal
│ ↓
│ 05B Wait - Wait for URL Analysis
│ ↓
│ 06B HTTP Request - Get URL Analysis
│ ↓
│ 07B Code - Normalize URL Enrichment
│
├── Domain
│ ↓
│ 04C HTTP Request - VirusTotal Domain Report
│ ↓
│ 05C Code - Normalize Domain Enrichment
│
└── Unknown
↓
04D Google Sheets - Save Unsupported IOC
06A / 07B / 05C
↓
08 Code - Calculate Threat Risk Score
↓
09 Google Sheets - Save Threat Intel Report
↓
10 IF - High Risk Indicator?
├── true
│ ↓
│ 11 Telegram - Send Threat Intel Alert
│ ↓
│ 12 Google Sheets - Update Action Taken
└── false
end
## Node Details
### 01 Webhook - Receive IOC
Receives the IOC submission.
Configuration:
HTTP Method: POST
Path: threat-intel-ioc
Authentication: None
Respond: Immediately
For production usage, authentication or a secret header should be added.
### 02 Code - Normalize and Detect IOC Type
Normalizes the submitted indicator and detects its type.
Output fields include:
reportId
timestamp
caseId
submittedBy
source
indicator
domain
indicatorType
status
notes
Supported types:
ip
url
domain
unknown
### 03 Switch - Route by IOC Type
Routes the IOC based on `indicatorType`.
Rules:
indicatorType = ip → IP branch
indicatorType = url → URL branch
indicatorType = domain → Domain branch
indicatorType = unknown → Unsupported branch
### 04A HTTP Request - AbuseIPDB IP Check
Checks the IP address reputation using AbuseIPDB.
Configuration:
Method: GET
URL: https://api.abuseipdb.com/api/v2/check
Query parameters:
ipAddress = {{ $('02 Code - Normalize and Detect IOC Type').item.json.indicator }}
maxAgeInDays = 90
Headers:
Key = YOUR_ABUSEIPDB_API_KEY
Accept = application/json
### 05A HTTP Request - VirusTotal IP Report
Retrieves the VirusTotal IP report.
Configuration:
Method: GET
URL: https://www.virustotal.com/api/v3/ip_addresses/{{ $('02 Code - Normalize and Detect IOC Type').item.json.indicator }}
Headers:
x-apikey = YOUR_VIRUSTOTAL_API_KEY
accept = application/json
### 06A Code - Normalize IP Enrichment
Normalizes AbuseIPDB and VirusTotal IP results into a common format.
Output fields include:
abuseIpdbScore
vtMalicious
vtSuspicious
vtHarmless
vtUndetected
enrichmentSource
notes
### 04B HTTP Request - Submit URL to VirusTotal
Submits a URL for VirusTotal analysis.
Configuration:
Method: POST
URL: https://www.virustotal.com/api/v3/urls
Body Content Type: Form URLencoded
Headers:
x-apikey = YOUR_VIRUSTOTAL_API_KEY
accept = application/json
Body:
url = {{ $('02 Code - Normalize and Detect IOC Type').item.json.indicator }}
### 05B Wait - Wait for URL Analysis
Waits before retrieving the VirusTotal URL analysis.
Recommended configuration:
Resume: After Time Interval
Amount: 20
Unit: Seconds
If VirusTotal returns `queued`, increase to `30–45 seconds`.
### 06B HTTP Request - Get URL Analysis
Retrieves the URL analysis result from VirusTotal.
Configuration:
Method: GET
URL: https://www.virustotal.com/api/v3/analyses/{{ $('04B HTTP Request - Submit URL to VirusTotal').item.json.data.id }}
Headers:
x-apikey = YOUR_VIRUSTOTAL_API_KEY
accept = application/json
### 07B Code - Normalize URL Enrichment
Normalizes the VirusTotal URL analysis result.
Output fields include:
vtStatus
vtMalicious
vtSuspicious
vtHarmless
vtUndetected
enrichmentSource
notes
### 04C HTTP Request - VirusTotal Domain Report
Retrieves the VirusTotal domain report.
Configuration:
Method: GET
URL: https://www.virustotal.com/api/v3/domains/{{ $('02 Code - Normalize and Detect IOC Type').item.json.indicator }}
Headers:
x-apikey = YOUR_VIRUSTOTAL_API_KEY
accept = application/json
### 05C Code - Normalize Domain Enrichment
Normalizes VirusTotal domain results.
Output fields include:
vtMalicious
vtSuspicious
vtHarmless
vtUndetected
vtDomainReputation
vtCategories
enrichmentSource
notes
### 04D Google Sheets - Save Unsupported IOC
Saves unsupported indicators in Google Sheets without calling any enrichment API.
Mapped values:
Risk Score = 0
Risk Level = Unsupported
Recommendation = Submit a valid IP address, URL, or domain for enrichment.
Action Taken = Logged only
Status = Unsupported
### 08 Code - Calculate Threat Risk Score
Calculates the final threat risk score.
Inputs:
AbuseIPDB Score
VirusTotal malicious detections
VirusTotal suspicious detections
Indicator type
VirusTotal domain reputation
VirusTotal analysis status
Output fields include:
riskScore
riskLevel
recommendation
actionTaken
status
riskReasons
notes
### 09 Google Sheets - Save Threat Intel Report
Saves the final enrichment report.
Google Sheet:
Threat Intel Pipeline
Tab:
Reports
### 10 IF - High Risk Indicator?
Checks if the final risk level is:
High
Critical
If true, the Telegram alert is sent.
### 11 Telegram - Send Threat Intel Alert
Sends a Telegram alert for high-risk or critical indicators.
### 12 Google Sheets - Update Action Taken
Updates the same Google Sheets row after the Telegram alert is sent.
Updated fields:
Action Taken = Telegram alert sent
Status = Notified
## Google Sheets Structure
Google Sheet:
Threat Intel Pipeline
Tab:
Reports
Columns:
Report ID
Timestamp
Case ID
Submitted By
Source
Indicator
Indicator Type
AbuseIPDB Score
VT Malicious
VT Suspicious
VT Harmless
VT Undetected
Risk Score
Risk Level
Recommendation
Action Taken
Status
Notes
Example row:
| Report ID | Timestamp | Case ID | Submitted By | Source | Indicator | Indicator Type | AbuseIPDB Score | VT Malicious | VT Suspicious | VT Harmless | VT Undetected | Risk Score | Risk Level | Recommendation | Action Taken | Status | Notes |
| --------- | -------------------- | -------- | ------------------------------------------------- | -------------------- | ------------- | -------------- | --------------: | -----------: | ------------: | ----------: | ------------: | ---------: | ---------- | ------------------------------------------------------- | ------------------- | -------- | -------------------- |
| 128 | 29/05/2026, 10:30:00 | CASE-001 | [analyst@example.com](mailto:analyst@example.com) | Manual Investigation | 185.220.101.1 | ip | 100 | 12 | 3 | 50 | 20 | 90 | High | Block or monitor the indicator and review related logs. | Telegram alert sent | Notified | AbuseIPDB score: 100 |
### IP Test
{
"indicator": "185.220.101.1",
"source": "Manual Investigation",
"caseId": "CASE-001",
"submittedBy": "analyst@example.com"
}
Expected result:
IOC detected as IP
AbuseIPDB enrichment runs
VirusTotal IP report runs
Risk score is calculated
Google Sheets report is saved
Telegram alert is sent if risk is High or Critical
### URL Test
{
"indicator": "http://fake-login-security-example.com/verify",
"source": "Phishing Investigation",
"caseId": "CASE-002",
"submittedBy": "analyst@example.com"
}
Expected result:
IOC detected as URL
VirusTotal URL submission runs
Workflow waits for analysis
VirusTotal URL analysis is retrieved
Risk score is calculated
Google Sheets report is saved
Telegram alert is sent if risk is High or Critical
### Domain Test
{
"indicator": "example.com",
"source": "Domain Investigation",
"caseId": "CASE-003",
"submittedBy": "analyst@example.com"
}
Expected result:
IOC detected as Domain
VirusTotal domain report runs
Risk score is calculated
Google Sheets report is saved
Telegram alert is sent if risk is High or Critical
### Unsupported IOC Test
{
"indicator": "not-a-valid-ioc",
"source": "Manual Test",
"caseId": "CASE-004",
"submittedBy": "analyst@example.com"
}
Expected result:
IOC detected as unknown
Unsupported IOC is saved in Google Sheets
No enrichment API is called
No Telegram alert is sent
## cURL Test Examples
### IP Test
curl -X POST "https://crmsolutions.app.n8n.cloud/webhook-test/threat-intel-ioc" \
-H "Content-Type: application/json" \
-d '{
"indicator": "185.220.101.1",
"source": "Manual Investigation",
"caseId": "CASE-001",
"submittedBy": "analyst@example.com"
}'
### URL Test
curl -X POST "https://crmsolutions.app.n8n.cloud/webhook-test/threat-intel-ioc" \
-H "Content-Type: application/json" \
-d '{
"indicator": "http://fake-login-security-example.com/verify",
"source": "Phishing Investigation",
"caseId": "CASE-002",
"submittedBy": "analyst@example.com"
}'
### Domain Test
curl -X POST "https://crmsolutions.app.n8n.cloud/webhook-test/threat-intel-ioc" \
-H "Content-Type: application/json" \
-d '{
"indicator": "example.com",
"source": "Domain Investigation",
"caseId": "CASE-003",
"submittedBy": "analyst@example.com"
}'
### Unsupported IOC Test
curl -X POST "https://crmsolutions.app.n8n.cloud/webhook-test/threat-intel-ioc" \
-H "Content-Type: application/json" \
-d '{
"indicator": "not-a-valid-ioc",
"source": "Manual Test",
"caseId": "CASE-004",
"submittedBy": "analyst@example.com"
}'
## Repository Screenshots
Add your screenshots below.
### IP Enrichment Execution

### URL Enrichment Execution

### Domain Enrichment Execution

### Threat Intel Report Sheet

## Security and Business Value
This project demonstrates an advanced threat intelligence enrichment workflow.
It helps security analysts automate repetitive IOC triage tasks by:
* receiving IOCs from external systems or analysts
* detecting IOC type automatically
* enriching IPs, URLs, and domains
* calculating a consistent risk score
* logging results in a central report
* sending alerts only when risk is high
* keeping unsupported submissions traceable
* SOC automation
* threat intelligence operations
* incident response triage
* phishing investigations
* firewall investigation workflows
* suspicious domain analysis
* case enrichment pipelines
## Possible Real-World Use Cases
This workflow can be adapted for:
* SIEM alert enrichment
* phishing email IOC analysis
* firewall alert triage
* suspicious IP/domain review
* SOC analyst manual submissions
* security case enrichment
* incident response investigation support
* automated blocklist review
## Future Improvements
Possible upgrades:
* Add URLScan.io enrichment
* Add WHOIS enrichment
* Add DNS resolution enrichment
* Add ASN and geolocation enrichment
* Add CISA KEV or CVE correlation
* Add multiple IOC batch processing
* Add support for file hashes
* Add support for IPv6
* Add support for email indicators
* Add Slack or Microsoft Teams alerts
* Add Jira/Trello/Notion ticket creation
* Add duplicate IOC detection
* Add case status tracking
* Add analyst approval workflow
* Add automatic blocklist update
* Add dashboard reporting
* Add scheduled threat intel summary reports
## Security Notes
Before using this in production:
* Protect the Webhook with authentication or a secret token.
* Do not expose API keys in screenshots or GitHub.
* Use n8n credentials or environment variables for secrets.
* Review AbuseIPDB and VirusTotal API rate limits.
* Avoid submitting sensitive internal indicators to third-party APIs without approval.
* Validate incoming payloads.
* Add error handling for API failures.
* Add retry logic for temporary API errors.
* Add deduplication to avoid repeated alerts.
* Protect Google Sheets access permissions.
* Treat this workflow as an enrichment aid, not a complete detection system.
## Project Status
Current version: working advanced demo
Implemented:
* Webhook IOC intake
* IOC normalization
* IOC type detection
* IP enrichment branch
* URL enrichment branch
* Domain enrichment branch
* Unsupported IOC logging
* AbuseIPDB integration
* VirusTotal integration
* Threat risk scoring
* Google Sheets reporting
* High/Critical risk IF logic
* Telegram alerting
* Google Sheets status update after alert
## Author
Built by **Iosif Castrucci**
GitHub: `iosif-castrucci-hub`
Email: `contact.iosifcastrucci@gmail.com`
## Disclaimer
This project is a demo cybersecurity automation workflow created for portfolio and educational purposes.
It is not a complete SOC, SIEM, SOAR, or threat intelligence platform and should not be used as the only method for making security decisions in production environments.
For production use, add authentication, input validation, error handling, deduplication, case management, secure credential storage, audit logging, and a formal incident response process.
## License
This repository is intended for portfolio and educational purposes.
You may adapt the workflow structure for your own projects.