Feeds API¶
Complete API reference for TrojanHorse.js threat intelligence feeds, including URLhaus, VirusTotal, AlienVault OTX, AbuseIPDB, and CrowdSec CTI integrations.
Overview¶
The Feeds API provides standardized interfaces for integrating with multiple threat intelligence sources, enabling real-time threat detection, correlation, and analysis across diverse data sources.
graph TB
A[Feeds API] --> B[URLhaus Feed]
A --> C[VirusTotal Feed]
A --> D[AlienVault OTX Feed]
A --> E[AbuseIPDB Feed]
A --> F[CrowdSec CTI Feed]
A --> G[Custom Feeds]
B --> B1[Malware URLs]
B --> B2[Payloads]
B --> B3[Signatures]
C --> C1[File Analysis]
C --> C2[URL Scanning]
C --> C3[Domain Reports]
D --> D1[Pulses]
D --> D2[IOCs]
D --> D3[Malware Families]
E --> E1[IP Reputation]
E --> E2[Abuse Reports]
E --> E3[Geolocation]
F --> F1[Behavioral Data]
F --> F2[Attack Patterns]
F --> F3[CTI Signals]
G --> G1[Custom Sources]
G --> G2[Internal Intel]
G --> G3[Community Feeds]
Base Feed Interface¶
ThreatFeed Abstract Class¶
All feed implementations extend the base ThreatFeed class which provides common functionality.
import { ThreatFeed } from 'trojanhorse-js/feeds';
// Base configuration options available to all feeds
const baseFeedConfig = {
// API configuration
apiKey: 'your-api-key', // API key for authentication
baseUrl: 'https://api.service.com', // Base API URL
timeout: 10000, // Request timeout in milliseconds
// Rate limiting
rateLimit: {
enabled: true, // Enable rate limiting
requestsPerMinute: 60, // Max requests per minute
requestsPerHour: 1000, // Max requests per hour
backoffStrategy: 'exponential' // 'linear', 'exponential'
},
// Caching
cache: {
enabled: true, // Enable response caching
ttl: 3600, // Cache TTL in seconds
maxSize: '100MB', // Maximum cache size
compression: true // Compress cached data
},
// Retry configuration
retry: {
enabled: true, // Enable automatic retries
maxAttempts: 3, // Maximum retry attempts
baseDelay: 1000, // Base delay in milliseconds
maxDelay: 30000, // Maximum delay in milliseconds
exponentialBackoff: true // Use exponential backoff
},
// Error handling
errorHandling: {
throwOnError: false, // Throw errors or return empty results
logErrors: true, // Log errors for debugging
fallbackToCache: true // Use cached data on errors
}
};
Common Methods¶
All feed classes implement these standard methods:
fetchThreatData(indicator, options)¶
Fetches threat intelligence data for a specific indicator.
const threatData = await feed.fetchThreatData('malicious-domain.com', {
includeMetadata: true, // Include additional metadata
includeHistory: false, // Include historical data
maxAge: 86400, // Maximum age of data in seconds
confidence: 'high', // Minimum confidence level
format: 'standard' // Output format
});
console.log('Threat data:', threatData);
batchQuery(indicators, options)¶
Performs batch queries for multiple indicators.
const indicators = ['domain1.com', 'domain2.com', '192.168.1.100'];
const batchResults = await feed.batchQuery(indicators, {
batchSize: 100, // Batch size for API calls
concurrency: 5, // Concurrent requests
waitBetweenBatches: 1000 // Wait time between batches
});
console.log('Batch results:', batchResults);
getHealthStatus()¶
Returns the current health status of the feed.
const health = await feed.getHealthStatus();
console.log('Feed health:', health);
// Returns:
// {
// status: 'healthy',
// lastSuccessfulRequest: '2025-01-15T10:30:00Z',
// requestCount: 1500,
// errorRate: 0.02,
// averageResponseTime: 250
// }
URLhaus Feed¶
URLhaus provides real-time information about malware URLs and payloads.
URLhausFeed Class¶
import { URLhausFeed } from 'trojanhorse-js/feeds';
const urlhausFeed = new URLhausFeed({
...baseFeedConfig,
apiKey: process.env.URLHAUS_API_KEY, // Optional for basic usage
// URLhaus-specific options
options: {
includeOffline: false, // Include offline URLs
maxAge: 30, // Max age in days
malwareFilter: ['trojan', 'ransomware'], // Filter by malware types
confidenceThreshold: 75 // Minimum confidence score
}
});
Methods¶
queryUrl(url, options)¶
Queries URLhaus for information about a specific URL.
const urlInfo = await urlhausFeed.queryUrl('http://malicious-site.com/payload.exe', {
includePayloads: true, // Include payload information
includeScreenshots: false, // Include screenshots
includeSubmissions: true // Include submission history
});
console.log('URL information:', urlInfo);
// Returns:
// {
// id: "12345",
// url: "http://malicious-site.com/payload.exe",
// url_status: "online",
// host: "malicious-site.com",
// date_added: "2025-01-15 10:30:00",
// threat: "trojan",
// blacklists: ["spamhaus", "surbl"],
// reporter: "anonymous",
// confidence: 85,
// payloads: [...],
// signatures: [...]
// }
queryHost(hostname, options)¶
Queries URLhaus for information about a specific host.
const hostInfo = await urlhausFeed.queryHost('malicious-domain.com', {
includeUrls: true, // Include URLs hosted on this domain
includeSubdomains: false, // Include subdomains
limit: 100 // Limit number of results
});
getRecentUrls(options)¶
Retrieves recently added malicious URLs.
const recentUrls = await urlhausFeed.getRecentUrls({
limit: 1000, // Number of URLs to retrieve
format: 'json', // Response format
excludeOffline: true // Exclude offline URLs
});
downloadPayload(payloadHash, options)¶
Downloads malware payload samples (requires API key).
const payload = await urlhausFeed.downloadPayload('sha256-hash', {
format: 'binary', // 'binary', 'base64'
password: 'infected', // ZIP password for payload
saveToFile: './payloads/sample.zip'
});
VirusTotal Feed¶
VirusTotal provides comprehensive file, URL, domain, and IP analysis.
VirusTotalFeed Class¶
import { VirusTotalFeed } from 'trojanhorse-js/feeds';
const virusTotalFeed = new VirusTotalFeed({
...baseFeedConfig,
apiKey: process.env.VIRUSTOTAL_API_KEY, // Required
// VirusTotal-specific options
options: {
publicApi: false, // Use public or private API
engines: ['sophos', 'kaspersky', 'avast'], // Specific engines
minDetections: 3, // Minimum detections to consider malicious
includeMetadata: true, // Include additional metadata
followRedirects: false // Follow URL redirects
}
});
Methods¶
scanFile(fileHash, options)¶
Retrieves analysis results for a file hash.
const fileReport = await virusTotalFeed.scanFile('sha256-hash', {
includeEngineDetails: true, // Include per-engine results
includeBehaviorAnalysis: true, // Include behavioral analysis
includeNetworkTraffic: false // Include network traffic analysis
});
console.log('File report:', fileReport);
// Returns:
// {
// sha256: "hash-value",
// md5: "md5-hash",
// sha1: "sha1-hash",
// scan_date: "2025-01-15 10:30:00",
// positives: 45,
// total: 70,
// permalink: "https://virustotal.com/file/...",
// scans: {
// "Sophos": { detected: true, result: "Mal/Generic-S" },
// "Kaspersky": { detected: true, result: "Trojan.Win32.Agent" }
// },
// behavioral_analysis: {...},
// network_traffic: {...}
// }
scanUrl(url, options)¶
Submits a URL for scanning and retrieves results.
const urlReport = await virusTotalFeed.scanUrl('http://suspicious-site.com', {
forceRescan: false, // Force new scan even if recent results exist
includeScreenshot: true, // Include website screenshot
includeWhoisData: true, // Include WHOIS information
followRedirects: true // Follow URL redirects
});
getDomainReport(domain, options)¶
Retrieves domain reputation and analysis data.
const domainReport = await virusTotalFeed.getDomainReport('suspicious-domain.com', {
includeSubdomains: true, // Include subdomain information
includePassiveDns: true, // Include passive DNS data
includeCommunicatingSamples: false, // Include communicating samples
includeDetectedReferrerSamples: false // Include detected referrer samples
});
getIpReport(ipAddress, options)¶
Retrieves IP address reputation and analysis data.
const ipReport = await virusTotalFeed.getIpReport('192.168.1.100', {
includePassiveDns: true, // Include passive DNS data
includeCommunicatingSamples: true, // Include communicating samples
includeDetectedDownloadedSamples: true, // Include detected samples
includeGeolocation: true // Include geolocation data
});
submitFile(filePath, options)¶
Submits a file for analysis.
const submission = await virusTotalFeed.submitFile('./sample.exe', {
password: 'infected', // Password for encrypted files
notifyUrl: 'https://callback.com/vt', // Callback URL for results
waitForResults: true, // Wait for analysis completion
timeout: 300000 // Timeout for waiting (5 minutes)
});
AlienVault OTX Feed¶
AlienVault Open Threat Exchange provides community-driven threat intelligence.
AlienVaultFeed Class¶
import { AlienVaultFeed } from 'trojanhorse-js/feeds';
const otxFeed = new AlienVaultFeed({
...baseFeedConfig,
apiKey: process.env.ALIENVAULT_API_KEY, // Required
// OTX-specific options
options: {
subscribedOnly: false, // Only subscribed pulses
modifiedSince: '2025-01-01', // Only pulses modified since date
includeInactive: false, // Include inactive pulses
tags: ['apt', 'malware'], // Filter by tags
authorUsername: null // Filter by specific author
}
});
Methods¶
getIndicatorDetails(indicator, options)¶
Retrieves detailed information about an indicator.
const details = await otxFeed.getIndicatorDetails('malicious-domain.com', {
section: 'general', // 'general', 'malware', 'url_list', 'passive_dns'
includeContext: true, // Include contextual information
includePulses: true, // Include associated pulses
limit: 50 // Limit number of results
});
console.log('Indicator details:', details);
searchPulses(query, options)¶
Searches for threat intelligence pulses.
const pulses = await otxFeed.searchPulses('APT29', {
sort: 'modified', // Sort by: 'created', 'modified', 'subscriber_count'
order: 'desc', // Order: 'asc', 'desc'
limit: 20, // Number of results
tags: ['apt', 'russia'], // Filter by tags
adversary: 'APT29' // Filter by adversary
});
getPulseDetails(pulseId, options)¶
Retrieves detailed information about a specific pulse.
const pulseDetails = await otxFeed.getPulseDetails('pulse-id-12345', {
includeIndicators: true, // Include all indicators
includeReferences: true, // Include reference URLs
includeValidation: false // Include validation information
});
getSubscribedPulses(options)¶
Retrieves pulses the user is subscribed to.
const subscribedPulses = await otxFeed.getSubscribedPulses({
modifiedSince: '2025-01-01', // Only recent modifications
limit: 100, // Number of pulses
includeInactive: false // Exclude inactive pulses
});
validateIndicator(indicator, options)¶
Validates an indicator against OTX intelligence.
const validation = await otxFeed.validateIndicator('suspicious-ip.com', {
sections: ['general', 'reputation', 'geo'], // Sections to check
includeContext: true, // Include context information
threshold: 3 // Minimum pulse count for positive
});
AbuseIPDB Feed¶
AbuseIPDB provides IP address reputation and abuse reporting data.
AbuseIPDBFeed Class¶
import { AbuseIPDBFeed } from 'trojanhorse-js/feeds';
const abuseipdbFeed = new AbuseIPDBFeed({
...baseFeedConfig,
apiKey: process.env.ABUSEIPDB_API_KEY, // Required
// AbuseIPDB-specific options
options: {
maxAgeInDays: 90, // Maximum age of reports
confidenceMinimum: 75, // Minimum confidence percentage
includeCountryMatch: true, // Include country match info
includeUsageType: true, // Include usage type (ISP, hosting, etc.)
verbose: true // Include verbose information
}
});
Methods¶
checkIp(ipAddress, options)¶
Checks an IP address for abuse reports.
const ipCheck = await abuseipdbFeed.checkIp('192.168.1.100', {
maxAgeInDays: 90, // Report age limit
verbose: true, // Include detailed information
includeReports: false // Include individual reports
});
console.log('IP check result:', ipCheck);
// Returns:
// {
// ipAddress: "192.168.1.100",
// isPublic: true,
// ipVersion: 4,
// isWhitelisted: false,
// abuseConfidencePercentage: 85,
// countryCode: "US",
// usageType: "Data Center/Web Hosting/Transit",
// isp: "Example ISP",
// domain: "example.com",
// totalReports: 45,
// numDistinctUsers: 12,
// lastReportedAt: "2025-01-15T10:30:00Z"
// }
reportIp(ipAddress, categories, comment, options)¶
Reports an abusive IP address.
const report = await abuseipdbFeed.reportIp('192.168.1.100', [18, 20], 'Brute force attack on SSH', {
timestamp: new Date().toISOString(), // When the abuse occurred
includeEvidence: true // Include supporting evidence
});
// Category codes:
// 3: Fraud Orders
// 4: DDoS Attack
// 9: Compromised
// 10: Web Spam
// 11: Email Spam
// 14: Port Scan
// 15: Hacking
// 16: SQL Injection
// 18: Brute Force
// 19: Bad Web Bot
// 20: Exploited Host
// 21: Web App Attack
// 22: SSH
// 23: IoT Targeted
getBlacklist(options)¶
Downloads the AbuseIPDB blacklist.
const blacklist = await abuseipdbFeed.getBlacklist({
confidenceMinimum: 90, // Minimum confidence percentage
limit: 10000, // Maximum number of IPs
plaintext: false, // Return as JSON instead of plaintext
onlyCountries: ['CN', 'RU'], // Filter by countries
exceptCountries: ['US', 'CA'] // Exclude specific countries
});
checkBlock(networkBlock, options)¶
Checks a network block (subnet) for abuse reports.
const blockCheck = await abuseipdbFeed.checkBlock('192.168.1.0/24', {
maxAgeInDays: 30, // Report age limit
includeReports: true // Include individual IP reports
});
clearAddress(ipAddress, options)¶
Clears (whitelists) an IP address from reports.
const clearResult = await abuseipdbFeed.clearAddress('192.168.1.100', {
reason: 'False positive - legitimate server',
evidence: 'Server logs showing normal behavior'
});
CrowdSec CTI Feed¶
CrowdSec Community Threat Intelligence provides behavioral analysis and attack patterns.
CrowdSecFeed Class¶
import { CrowdSecFeed } from 'trojanhorse-js/feeds';
const crowdsecFeed = new CrowdSecFeed({
...baseFeedConfig,
apiKey: process.env.CROWDSEC_API_KEY, // Required
// CrowdSec-specific options
options: {
machineId: 'trojanhorse-instance', // Machine identifier
scenarios: ['ssh-bf', 'http-bf'], // Specific scenarios to track
includeMetrics: true, // Include behavioral metrics
includeSignatures: true, // Include attack signatures
confidenceThreshold: 80 // Minimum confidence level
}
});
Methods¶
getIpInfo(ipAddress, options)¶
Retrieves behavioral information about an IP address.
const ipInfo = await crowdsecFeed.getIpInfo('192.168.1.100', {
includeBehaviors: true, // Include behavioral analysis
includeScenarios: true, // Include triggered scenarios
includeTargets: true, // Include target information
includeGeolocation: true // Include geo data
});
console.log('IP behavioral info:', ipInfo);
// Returns:
// {
// ip: "192.168.1.100",
// ip_range: "192.168.1.0/24",
// as_name: "Example ISP",
// as_num: 12345,
// location: { country: "US", city: "New York" },
// reputation: "malicious",
// behaviors: [
// { name: "ssh:bruteforce", label: "SSH Bruteforce" },
// { name: "http:scan", label: "HTTP Scanning" }
// ],
// history: {
// first_seen: "2025-01-01T00:00:00Z",
// last_seen: "2025-01-15T10:30:00Z",
// full_age: 14,
// days_age: 14
// },
// scores: {
// overall: { aggressiveness: 4, threat: 4, trust: 1, anomaly: 3 },
// last_day: { aggressiveness: 3, threat: 3, trust: 1, anomaly: 2 }
// },
// target_countries: { "US": 45, "FR": 23, "DE": 15 }
// }
searchIps(query, options)¶
Searches for IPs based on various criteria.
const searchResults = await crowdsecFeed.searchIps({
range: '192.168.0.0/16', // IP range to search
scenarios: ['ssh-bf', 'http-bf'], // Scenarios to filter by
behaviors: ['tcp:scan', 'http:exploit'], // Behaviors to filter by
countries: ['CN', 'RU'], // Countries to filter by
as_num: [12345, 67890], // AS numbers to filter by
since: '2025-01-01', // Results since date
until: '2025-01-15' // Results until date
}, {
limit: 1000, // Maximum results
format: 'json' // Response format
});
getScenarios(options)¶
Retrieves available attack scenarios.
const scenarios = await crowdsecFeed.getScenarios({
type: 'community', // 'community', 'custom', 'all'
includeMetrics: true, // Include usage metrics
activeOnly: true // Only active scenarios
});
getBehaviors(options)¶
Retrieves behavioral patterns and attack types.
const behaviors = await crowdsecFeed.getBehaviors({
category: 'attack', // 'attack', 'scan', 'abuse'
includeDescriptions: true, // Include detailed descriptions
includeExamples: true // Include example signatures
});
reportDecision(ipAddress, decision, options)¶
Reports a decision (block/allow) for an IP address.
const report = await crowdsecFeed.reportDecision('192.168.1.100', {
type: 'ban', // 'ban', 'captcha', 'throttle'
duration: '4h', // Decision duration
scenario: 'manual-ban', // Scenario that triggered decision
reason: 'Repeated brute force attempts',
origin: 'cscli', // Origin of decision
scope: 'Ip', // Scope: 'Ip', 'Range', 'AS', 'Country'
value: '192.168.1.100' // Value being decided upon
});
Custom Feed Implementation¶
Creating Custom Feeds¶
You can create custom feed implementations by extending the base ThreatFeed class.
import { ThreatFeed } from 'trojanhorse-js/feeds';
class CustomThreatFeed extends ThreatFeed {
constructor(config) {
super(config);
this.name = 'CustomFeed';
this.version = '1.0.0';
this.baseUrl = config.baseUrl;
}
async fetchThreatData(indicator, options = {}) {
try {
// Implement custom API call
const response = await this.makeRequest('GET', `/api/threat/${indicator}`, {
params: {
format: 'json',
include_metadata: options.includeMetadata || false
}
});
// Transform response to standard format
return this.transformResponse(response.data, indicator);
} catch (error) {
return this.handleError(error, indicator);
}
}
transformResponse(data, indicator) {
// Transform API response to standard ThreatFeedResult format
return {
indicator: indicator,
type: this.detectIndicatorType(indicator),
threat: data.malicious,
confidence: data.confidence_score,
sources: [this.name],
timestamp: new Date(data.scan_date).toISOString(),
metadata: {
source: this.name,
api_version: this.version,
threat_types: data.threat_categories,
scan_engines: data.engines_count,
additional_info: data.extra_data
},
// Additional fields for correlation
correlationScore: data.correlation_score,
consensusLevel: data.consensus_level
};
}
async batchQuery(indicators, options = {}) {
// Implement batch processing
const batchSize = options.batchSize || 100;
const results = [];
for (let i = 0; i < indicators.length; i += batchSize) {
const batch = indicators.slice(i, i + batchSize);
const batchResults = await this.processBatch(batch, options);
results.push(...batchResults);
// Rate limiting delay between batches
if (i + batchSize < indicators.length) {
await this.delay(options.waitBetweenBatches || 1000);
}
}
return results;
}
async processBatch(indicators, options) {
// Process a batch of indicators
const promises = indicators.map(indicator =>
this.fetchThreatData(indicator, options)
);
return await Promise.allSettled(promises).then(results =>
results.map(result =>
result.status === 'fulfilled' ? result.value : null
).filter(Boolean)
);
}
async getHealthStatus() {
try {
const response = await this.makeRequest('GET', '/api/health');
return {
status: 'healthy',
lastSuccessfulRequest: new Date().toISOString(),
apiVersion: response.data.version,
requestCount: this.requestCount,
errorRate: this.errorCount / this.requestCount,
averageResponseTime: this.averageResponseTime
};
} catch (error) {
return {
status: 'unhealthy',
error: error.message,
lastSuccessfulRequest: this.lastSuccessfulRequest,
requestCount: this.requestCount,
errorRate: this.errorCount / this.requestCount
};
}
}
}
// Use custom feed
const customFeed = new CustomThreatFeed({
apiKey: 'your-api-key',
baseUrl: 'https://api.customfeed.com',
rateLimit: { requestsPerMinute: 30 }
});
// Register with TrojanHorse
trojan.registerFeed('custom', customFeed);
Feed Registry¶
// Feed registry for managing multiple feeds
import { FeedRegistry } from 'trojanhorse-js/feeds';
const registry = new FeedRegistry();
// Register feeds
registry.register('urlhaus', urlhausFeed);
registry.register('virustotal', virusTotalFeed);
registry.register('otx', otxFeed);
registry.register('abuseipdb', abuseipdbFeed);
registry.register('crowdsec', crowdsecFeed);
registry.register('custom', customFeed);
// Query all feeds
const allResults = await registry.queryAll('malicious-domain.com', {
includeMetadata: true,
timeout: 10000,
failFast: false // Don't stop on first error
});
// Query specific feeds
const selectedResults = await registry.queryFeeds(
['virustotal', 'otx', 'custom'],
'suspicious-ip.com'
);
// Get feed statistics
const stats = registry.getStatistics();
console.log('Feed statistics:', stats);
Error Handling¶
Feed Error Types¶
import {
FeedError,
ApiKeyError,
RateLimitError,
TimeoutError,
NetworkError
} from 'trojanhorse-js/feeds';
// Handle different error types
try {
const result = await feed.fetchThreatData(indicator);
} catch (error) {
if (error instanceof ApiKeyError) {
console.error('API key invalid or expired');
} else if (error instanceof RateLimitError) {
console.error('Rate limit exceeded, retrying after:', error.retryAfter);
} else if (error instanceof TimeoutError) {
console.error('Request timed out');
} else if (error instanceof NetworkError) {
console.error('Network connectivity issue');
} else {
console.error('Unknown feed error:', error.message);
}
}
Next Steps: - Review Core API for main TrojanHorse.js functionality - Check Security API for encryption and authentication - Explore Integrations API for external system connections