How to Add Custom Threat Intelligence Feeds to SpiderFoot: A Complete Guide
Use the built-in sfp_customfeed module to import any JSON-based indicator list into SpiderFoot without modifying core code.
SpiderFoot ships with a generic Custom Feed plugin that transforms your own threat intelligence into first-class scan events. Located at modules/sfp_customfeed.py in the smicallef/spiderfoot repository, this plugin reads a JSON file of indicators and injects them into SpiderFoot's event pipeline for correlation and enrichment alongside data from 200+ built-in modules.
How the Custom Feed Plugin Works
The sfp_customfeed module implements the standard SpiderFootPlugin interface, giving your custom indicators the same capabilities as commercial threat feeds. Here's the execution flow based on the source code:
- Configuration loading — Reads the
customfeedoption from scan profile or CLI (lines 19-28) - JSON parsing — Validates and loads the feed file using
json.load(); malformed JSON aborts with a clear error (lines 31-38) - Event creation — Calls
self.sf.createEvent()for each indicator, mappingtypeandvalueplus optional metadata (lines 59-77) - Event publication — Adds events to the global queue for consumption by correlation modules (lines 78-82)
Because the plugin uses SpiderFoot's internal self.sf API, your custom indicators automatically participate in cross-module correlation, enrichment chaining, and report generation without any code changes.
Required JSON Format for Custom Feeds
Each indicator object requires two mandatory fields and supports three optional metadata fields:
| Field | Required | Description |
|---|---|---|
type |
✅ | SpiderFoot event type: ipv4, ipv6, domain, hostname, email, url, hash, etc. |
value |
✅ | Raw indicator string (IP address, domain name, hash, etc.) |
source |
❌ | Custom provenance label for tracking (appears in event metadata) |
confidence |
❌ | Integer 0-100 representing confidence score |
description |
❌ | Human-readable context about the indicator |
Example Custom Feed File
Create a file named myfeed.json:
[
{
"type": "ipv4",
"value": "198.51.100.23",
"source": "MyInternalIPList",
"confidence": 95,
"description": "Known compromised host from SOC alert"
},
{
"type": "domain",
"value": "malicious.example.com",
"source": "InternalPhishingFeed",
"confidence": 80,
"description": "Phishing landing page identified by abuse desk"
},
{
"type": "email",
"value": "badguy@evil.org",
"source": "CompromisedCredentials",
"confidence": 90,
"description": "Credential from 2023 breach corpus"
},
{
"type": "hash",
"value": "d41d8cd98f00b204e9800998ecf8427e",
"source": "MalwareLab",
"confidence": 100,
"description": "Confirmed Lazarus group sample"
}
]
Enabling the Custom Feed Module
Method 1: Scan Profile Configuration
Add to your profile JSON (e.g., profiles/custom-intel.json):
{
"modules": {
"sfp_customfeed": {
"enabled": true,
"customfeed": "/path/to/myfeed.json"
},
"sfp_dnsresolve": {
"enabled": true
},
"sfp_whois": {
"enabled": true
}
}
}
Run with:
python sf.py -s corp-target.com -p profiles/custom-intel.json
Method 2: Command-Line Options
python sf.py -s corp-target.com \
-m sfp_customfeed,sfp_dnsresolve \
-o customfeed=/path/to/myfeed.json
Method 3: Docker Deployment
docker run --rm \
-v $(pwd)/myfeed.json:/data/myfeed.json:ro \
spiderfoot/spiderfoot \
-s corp-target.com \
-m sfp_customfeed \
-o customfeed=/data/myfeed.json
Verifying Custom Feed Integration
During scan startup, monitor logs for confirmation:
[+] SpiderFoot 3.5.0 initialized
[+] Loaded 201 modules
[+] sfp_customfeed - Loaded 4 indicators from /path/to/myfeed.json
[+] sfp_customfeed - Created event ipv4:198.51.100.23 (source: MyInternalIPList, confidence: 95)
[+] sfp_customfeed - Created event domain:malicious.example.com (source: InternalPhishingFeed, confidence: 80)
[+] sfp_customfeed - Created event email:badguy@evil.org (source: CompromisedCredentials, confidence: 90)
[+] sfp_customfeed - Created event hash:d41d8cd98f00b204e9800998ecf8427e (source: MalwareLab, confidence: 100)
Your custom indicators now flow through SpiderFoot's standard pipeline. The sfp_dnsresolve module will resolve IP-domain relationships, sfp_abusech will check blocklists, and sfp_correlations will flag matches against other discovered assets.
Programmatic Access to Custom Events
When embedding SpiderFoot as a library, retrieve custom events by source label:
import spiderfoot.sf as sf
engine = sf.SpiderFootEngine()
engine.setTarget('corp-target.com')
engine.enableModule('sfp_customfeed')
engine.setOption('sfp_customfeed.customfeed', '/path/to/myfeed.json')
engine.start()
# Extract all events from scan
all_events = engine.getEvents()
# Filter for your custom feed sources
intel_sources = {'MyInternalIPList', 'InternalPhishingFeed', 'CompromisedCredentials', 'MalwareLab'}
custom_intel = [
e for e in all_events
if e.get('source') in intel_sources
]
# Group by indicator type
from collections import defaultdict
by_type = defaultdict(list)
for event in custom_intel:
by_type[event.get('type')].append(event.get('value'))
print(f"Loaded {len(custom_intel)} custom indicators:")
for evt_type, values in by_type.items():
print(f" {evt_type}: {len(values)} indicators")
Key Files and Source References
| File | Purpose | Lines |
|---|---|---|
modules/sfp_customfeed.py |
Core plugin implementation | 19-82 |
spiderfoot/event.py |
Event class instantiated by plugin | Full file |
spiderfoot/plugin.py |
Base SpiderFootPlugin class |
Full file |
sf.py |
CLI entry point for scan orchestration | Full file |
Supported Event Types for Custom Feeds
The type field accepts any valid SpiderFoot event type. Common values include:
- Network:
ipv4,ipv6,domain,hostname,url,netblock - Identity:
email,username,person_name,phone_number - Threat:
hash,hash_md5,hash_sha1,hash_sha256,malware_name - Infrastructure:
port,banner,geoip,certificate - Content:
raw_rfi,raw_sql_injection,raw_xss
Consult spiderfoot/event.py for the complete enumeration.
Summary
- Prepare JSON — Create a structured indicator file with
typeandvaluerequired fields - Enable plugin — Activate
sfp_customfeedvia scan profile or CLI optioncustomfeed= - Run scan — Indicators automatically become SpiderFoot events for correlation and reporting
- No core modifications — The plugin uses standard
SpiderFootPlugininterface andself.sf.createEvent()API
Your custom threat intelligence receives identical treatment to commercial feeds, enabling seamless integration with SpiderFoot's enrichment, correlation, and visualization capabilities.
Frequently Asked Questions
What happens if my JSON file is malformed?
SpiderFoot aborts the scan immediately with a descriptive error. The plugin wraps json.load() in exception handling at lines 31-38 of sfp_customfeed.py, surfacing parse errors like JSONDecodeError: Expecting property name enclosed in double quotes before any events are generated.
Can I use multiple custom feed files in one scan?
Yes. Enable multiple instances by creating separate scan profiles or running sequential scans with different -o customfeed= values. Each scan loads its specified feed independently; there is no built-in merging of multiple JSON files within a single plugin instance.
Do custom feed indicators trigger automatic enrichment?
Absolutely. Once sfp_customfeed publishes events to the global queue, any enabled module observing those event types will process them. A domain indicator will trigger sfp_dnsresolve, sfp_whoxy, and sfp_abusech if those modules are active in your scan configuration.
Is there a size limit for custom feed files?
No hardcoded limit exists in the plugin source. However, extremely large files (100K+ indicators) may impact startup time and memory usage since the entire JSON array loads into memory before event generation begins. For production-scale feeds, consider splitting into multiple scans or implementing a custom streaming plugin using the same SpiderFootPlugin base class.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →