Vulnerability Management Webhooks
Webhook Configuration To set up webhooks for your integration, visit the Unizo Console Webhooks section for step-by-step configuration guide.
Overview
Unizo's Vulnerability Management API provides webhooks to notify your application when important vulnerability events occur across your security scanning and vulnerability management platforms. These real-time notifications enable you to build automated remediation workflows, maintain security posture, track vulnerability lifecycle, and ensure compliance with security policies.
Our platform normalizes webhook events from various vulnerability management providers (Qualys, Tenable, Rapid7, CrowdStrike, etc.) into a consistent format, making it easy to handle vulnerability events across different scanning platforms.
Supported Event Types
Event Type Description Trigger Conditions Triggered when new vulnerabilities are discovered Triggered when vulnerability details are updated Triggered when a vulnerability is remediated Triggered when remediation is verified Triggered when a vulnerability scan begins Triggered when a vulnerability scan completes Triggered when a scan fails Triggered when an asset's risk score changes Triggered when a patch becomes available Triggered when compliance violations are detected
Webhook Security All webhooks from Unizo include security headers to verify authenticity:
Headers Header Description x-unizo-event-typeThe type of event that triggered the webhook x-unizo-signatureHMAC SHA-256 signature for request validation x-unizo-timestampUnix timestamp when the event was sent x-unizo-delivery-idUnique identifier for this webhook delivery
Signature Verification Verify the authenticity of incoming webhooks using HMAC SHA-256:
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
Event Details
Vulnerability Events
Triggered when new vulnerabilities are discovered during scans or continuous monitoring of your infrastructure.
Headers Name Type Required Description Content-Typestring Yes Always application/json x-unizo-event-typestring Yes Event type: vulnerability:discovered x-unizo-webhook-idstring Yes Unique webhook configuration ID x-unizo-delivery-idstring Yes Unique delivery attempt ID x-unizo-signaturestring Yes HMAC SHA256 signature for verification
Request Body Schema Property Type Required Description typestring Yes Event type identifier versionstring Yes Webhook payload version data.vulnerability.idstring Yes Unique vulnerability identifier data.vulnerability.cve_idstring No CVE identifier if available data.vulnerability.titlestring Yes Vulnerability title data.vulnerability.descriptionstring Yes Detailed description data.vulnerability.severitystring Yes Severity level (critical, high, medium, low, info) data.vulnerability.cvss_scorenumber No CVSS score (0-10) data.vulnerability.cvss_vectorstring No CVSS vector string data.vulnerability.discovered_atstring Yes Discovery timestamp (ISO 8601) data.vulnerability.categorystring No Vulnerability category data.vulnerability.exploit_availableboolean No Whether exploit is publicly available data.affected_assetsarray Yes List of affected assets data.remediation.availableboolean Yes Whether remediation is available data.remediation.typestring No Remediation type (patch, configuration, upgrade, workaround) data.remediation.descriptionstring No Remediation instructions data.remediation.effortstring No Remediation effort (low, medium, high) data.scan_idstring No Associated scan ID integration.idstring Yes Integration ID integration.namestring Yes Integration name integration.providerstring Yes VMS provider name
Example Payload Copy {
"type" : "vulnerability:discovered" ,
"version" : "1.0.0" ,
"data" : {
"vulnerability" : {
"id" : "vuln_abc123" ,
"cve_id" : "CVE-2024-12345" ,
"title" : "Remote Code Execution in Apache Log4j" ,
"description" : "A critical vulnerability allowing remote code execution through crafted log messages" ,
"severity" : "critical" ,
"cvss_score" : 10 ,
"cvss_vector" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H" ,
"discovered_at" : "2024-06-15T14:30:00Z" ,
"category" : "Remote Code Execution" ,
"exploit_available" : true
} ,
"affected_assets" : [
{
"id" : "asset_srv_001" ,
"hostname" : "prod-api-01" ,
"ip_address" : "10.0.1.50" ,
"os" : "Ubuntu 20.04" ,
"criticality" : "critical"
} ,
{
"id" : "asset_srv_002" ,
"hostname" : "prod-api-02" ,
"ip_address" : "10.0.1.51" ,
"os" : "Ubuntu 20.04" ,
"criticality" : "critical"
}
] ,
"remediation" : {
"available" : true ,
"type" : "patch" ,
"description" : "Update Log4j to version 2.17.0 or later" ,
"effort" : "low"
} ,
"scan_id" : "scan_123456"
} ,
"integration" : {
"id" : "int_qualys_789" ,
"name" : "Company Qualys" ,
"provider" : "qualys"
}
}
Response 200 OKWebhook processed successfully 400 Bad RequestInvalid webhook payload 401 UnauthorizedInvalid or missing signature
Triggered when a vulnerability has been successfully remediated through patching, configuration changes, or other mitigation measures.
Headers Name Type Required Description Content-Typestring Yes Always application/json x-unizo-event-typestring Yes Event type: vulnerability:remediated x-unizo-webhook-idstring Yes Unique webhook configuration ID x-unizo-delivery-idstring Yes Unique delivery attempt ID x-unizo-signaturestring Yes HMAC SHA256 signature for verification
Request Body Schema Property Type Required Description typestring Yes Event type identifier versionstring Yes Webhook payload version data.vulnerability_idstring Yes Vulnerability identifier data.cve_idstring No CVE identifier data.remediation.methodstring Yes Remediation method (patched, configured, removed, mitigated) data.remediation.applied_atstring Yes Remediation timestamp (ISO 8601) data.remediation.applied_by.idstring Yes User or system ID data.remediation.applied_by.namestring Yes Name data.remediation.applied_by.typestring Yes Remediation source (user, automated) data.remediation.detailsstring No Remediation details data.remediation.verification_statusstring Yes Verification status (pending, verified, failed) data.affected_assetsarray Yes Assets where vulnerability was remediated data.time_to_remediateinteger No Time from discovery to remediation in seconds integration.idstring Yes Integration ID integration.namestring Yes Integration name integration.providerstring Yes VMS provider name
Example Payload Copy {
"type" : "vulnerability:remediated" ,
"version" : "1.0.0" ,
"data" : {
"vulnerability_id" : "vuln_abc123" ,
"cve_id" : "CVE-2024-12345" ,
"remediation" : {
"method" : "patched" ,
"applied_at" : "2024-06-15T16:00:00Z" ,
"applied_by" : {
"id" : "auto_patch_system" ,
"name" : "Automated Patching System" ,
"type" : "automated"
} ,
"details" : "Applied security update package log4j-2.17.0" ,
"verification_status" : "verified"
} ,
"affected_assets" : [
{
"id" : "asset_srv_001" ,
"hostname" : "prod-api-01" ,
"status" : "remediated"
} ,
{
"id" : "asset_srv_002" ,
"hostname" : "prod-api-02" ,
"status" : "remediated"
}
] ,
"time_to_remediate" : 5400
} ,
"integration" : {
"id" : "int_tenable_456" ,
"name" : "Company Tenable" ,
"provider" : "tenable"
}
}
Response 200 OKWebhook processed successfully 400 Bad RequestInvalid webhook payload 401 UnauthorizedInvalid or missing signature
Scan Events
Triggered when a vulnerability scan completes, providing summary results and discovered issues.
Headers Name Type Required Description Content-Typestring Yes Always application/json x-unizo-event-typestring Yes Event type: scan:completed x-unizo-webhook-idstring Yes Unique webhook configuration ID x-unizo-delivery-idstring Yes Unique delivery attempt ID x-unizo-signaturestring Yes HMAC SHA256 signature for verification
Request Body Schema Property Type Required Description typestring Yes Event type identifier versionstring Yes Webhook payload version data.scan.idstring Yes Scan identifier data.scan.namestring Yes Scan name data.scan.typestring Yes Scan type (vulnerability, compliance, discovery, web_app) data.scan.started_atstring Yes Scan start time (ISO 8601) data.scan.completed_atstring Yes Scan completion time (ISO 8601) data.scan.durationinteger No Scan duration in seconds data.scan.scanner_versionstring No Scanner version used data.summary.assets_scannedinteger Yes Number of assets scanned data.summary.vulnerabilities_found.criticalinteger Yes Critical vulnerabilities data.summary.vulnerabilities_found.highinteger Yes High severity vulnerabilities data.summary.vulnerabilities_found.mediuminteger Yes Medium severity vulnerabilities data.summary.vulnerabilities_found.lowinteger Yes Low severity vulnerabilities data.summary.vulnerabilities_found.infointeger No Informational findings data.summary.vulnerabilities_found.totalinteger Yes Total vulnerabilities data.summary.new_vulnerabilitiesinteger No Newly discovered vulnerabilities data.summary.remediated_since_lastinteger No Vulnerabilities remediated since last scan data.summary.compliance_scorenumber No Compliance score percentage data.top_vulnerabilitiesarray No Most critical vulnerabilities found integration.idstring Yes Integration ID integration.namestring Yes Integration name integration.providerstring Yes VMS provider name
Example Payload Copy {
"type" : "scan:completed" ,
"version" : "1.0.0" ,
"data" : {
"scan" : {
"id" : "scan_789xyz" ,
"name" : "Weekly Infrastructure Scan" ,
"type" : "vulnerability" ,
"started_at" : "2024-06-15T02:00:00Z" ,
"completed_at" : "2024-06-15T04:30:00Z" ,
"duration" : 9000 ,
"scanner_version" : "Qualys VMDR 2.5"
} ,
"summary" : {
"assets_scanned" : 250 ,
"vulnerabilities_found" : {
"critical" : 5 ,
"high" : 23 ,
"medium" : 87 ,
"low" : 156 ,
"info" : 342 ,
"total" : 613
} ,
"new_vulnerabilities" : 12 ,
"remediated_since_last" : 45 ,
"compliance_score" : 78.5
} ,
"top_vulnerabilities" : [
{
"id" : "vuln_log4j" ,
"cve_id" : "CVE-2024-12345" ,
"severity" : "critical" ,
"affected_assets" : 15
} ,
{
"id" : "vuln_openssl" ,
"cve_id" : "CVE-2024-23456" ,
"severity" : "critical" ,
"affected_assets" : 8
}
]
} ,
"integration" : {
"id" : "int_rapid7_123" ,
"name" : "Company Rapid7" ,
"provider" : "rapid7"
}
}
Response 200 OKWebhook processed successfully 400 Bad RequestInvalid webhook payload 401 UnauthorizedInvalid or missing signature
Asset Events
Triggered when an asset's risk score changes significantly due to new vulnerabilities, remediation, or criticality updates.
Headers Name Type Required Description Content-Typestring Yes Always application/json x-unizo-event-typestring Yes Event type: asset:risk_changed x-unizo-webhook-idstring Yes Unique webhook configuration ID x-unizo-delivery-idstring Yes Unique delivery attempt ID x-unizo-signaturestring Yes HMAC SHA256 signature for verification
Request Body Schema Property Type Required Description typestring Yes Event type identifier versionstring Yes Webhook payload version data.asset.idstring Yes Asset ID data.asset.hostnamestring Yes Hostname data.asset.ip_addressstring No IP address data.asset.typestring No Asset type data.asset.criticalitystring Yes Business criticality data.risk_change.previous_scoreinteger Yes Previous risk score (0-100) data.risk_change.current_scoreinteger Yes Current risk score (0-100) data.risk_change.previous_levelstring Yes Previous risk level (low, medium, high, critical) data.risk_change.current_levelstring Yes Current risk level (low, medium, high, critical) data.risk_change.change_reasonstring Yes Primary reason for change data.risk_change.changed_atstring Yes Change timestamp (ISO 8601) data.vulnerability_summary.criticalinteger Yes Number of critical vulnerabilities data.vulnerability_summary.highinteger Yes Number of high vulnerabilities data.vulnerability_summary.mediuminteger Yes Number of medium vulnerabilities data.vulnerability_summary.lowinteger Yes Number of low vulnerabilities data.vulnerability_summary.exploitableinteger No Vulnerabilities with known exploits data.recommended_actionsarray No Recommended response actions integration.idstring Yes Integration ID integration.namestring Yes Integration name integration.providerstring Yes VMS provider name
Example Payload Copy {
"type" : "asset:risk_changed" ,
"version" : "1.0.0" ,
"data" : {
"asset" : {
"id" : "asset_db_001" ,
"hostname" : "prod-database-01" ,
"ip_address" : "10.0.2.100" ,
"type" : "Database Server" ,
"criticality" : "critical"
} ,
"risk_change" : {
"previous_score" : 65 ,
"current_score" : 92 ,
"previous_level" : "medium" ,
"current_level" : "critical" ,
"change_reason" : "New critical vulnerability with active exploit detected" ,
"changed_at" : "2024-06-15T15:00:00Z"
} ,
"vulnerability_summary" : {
"critical" : 3 ,
"high" : 7 ,
"medium" : 15 ,
"low" : 23 ,
"exploitable" : 4
} ,
"recommended_actions" : [
"Immediately patch CVE-2024-12345" ,
"Apply database security configuration baseline" ,
"Enable advanced threat detection" ,
"Review database access controls"
]
} ,
"integration" : {
"id" : "int_crowdstrike_789" ,
"name" : "Company CrowdStrike" ,
"provider" : "crowdstrike"
}
}
Response 200 OKWebhook processed successfully 400 Bad RequestInvalid webhook payload 401 UnauthorizedInvalid or missing signature
Webhook Delivery & Retries
Unizo implements a robust delivery system with automatic retries to ensure your webhooks are delivered reliably:
Timeout : 30 seconds per delivery attempt
Retry Schedule : 5 attempts with exponential backoff
Attempt 1: Immediate
Attempt 2: 1 minute delay
Attempt 3: 5 minutes delay
Attempt 4: 30 minutes delay
Attempt 5: 2 hours delay
Success Criteria : HTTP status codes 200-299
Failure Handling : After 5 failed attempts, the webhook is marked as failed
Best Practices
1. Idempotency
Always implement idempotent webhook handlers using the x-unizo-delivery-id header:
Idempotent Webhook Handler // Example: Handling webhooks idempotently
app.post('/webhooks/vms', async (req, res) => {
const deliveryId = req.headers['x-unizo-delivery-id'];
// Check if we've already processed this delivery
const existingDelivery = await db.webhookDeliveries.findOne({
deliveryId
});
if (existingDelivery) {
console.log(`Duplicate delivery detected: ${deliveryId}`);
return res.status(200).json({
status: 'already_processed'
});
}
// Process the webhook
try {
await processVulnerabilityEvent(req.body);
// Record the delivery
await db.webhookDeliveries.create({
deliveryId,
processedAt: new Date()
});
res.status(200).json({ status: 'success' });
} catch (error) {
console.error('Webhook processing failed:', error);
res.status(500).json({ status: 'error' });
}
});
Implement automated remediation based on vulnerability events:
Automated Vulnerability Remediation // Example: Automated remediation workflow
app.post('/webhooks/vms', async (req, res) => {
const { type, data } = req.body;
// Acknowledge receipt
res.status(200).json({ status: 'received' });
switch (type) {
case 'vulnerability:discovered':
// Check if automated remediation is possible
if (data.vulnerability.severity === 'critical' &&
data.remediation.available &&
data.remediation.effort === 'low') {
// Create change request
const changeRequest = await itsmApi.createChange({
type: 'emergency',
title: `Critical vulnerability: ${data.vulnerability.cve_id}`,
description: data.vulnerability.description,
impact: data.affected_assets.length,
remediation: data.remediation.description
});
// Schedule automated patching
for (const asset of data.affected_assets) {
if (asset.criticality !== 'critical') {
await patchingApi.scheduleUpdate({
assetId: asset.id,
vulnerability: data.vulnerability.id,
changeRequest: changeRequest.id,
window: 'next-maintenance'
});
} else {
// Critical assets need approval
await notificationApi.requestApproval({
to: 'security-team@company.com',
asset: asset,
vulnerability: data.vulnerability,
action: 'emergency-patch'
});
}
}
}
break;
case 'asset:risk_changed':
// Trigger response based on risk level
if (data.risk_change.current_level === 'critical') {
// Isolate high-risk assets
await networkApi.applySecurityPolicy({
assetId: data.asset.id,
policy: 'restricted-access',
reason: `Risk score increased to ${data.risk_change.current_score}`
});
// Create incident
await incidentApi.create({
title: `Critical risk: ${data.asset.hostname}`,
priority: 'P1',
description: `Asset risk increased due to: ${data.risk_change.change_reason}`,
assignTo: 'security-operations'
});
}
break;
}
});
3. Compliance and Reporting
Track vulnerability metrics for compliance and reporting:
Vulnerability Compliance Tracking // Example: Compliance tracking and reporting
app.post('/webhooks/vms', async (req, res) => {
const { type, data, integration } = req.body;
// Track metrics
const metrics = {
timestamp: new Date(),
eventType: type,
integration: integration.name,
vulnerabilityId: data.vulnerability?.id,
severity: data.vulnerability?.severity
};
switch (type) {
case 'scan:completed':
// Update compliance dashboard
await complianceDb.scanResults.create({
scanId: data.scan.id,
scanType: data.scan.type,
timestamp: data.scan.completed_at,
results: data.summary,
complianceScore: data.summary.compliance_score
});
// Check SLA compliance
const slaTarget = getSLAForScanType(data.scan.type);
const meanTimeToScan = await calculateMTTS(data.scan.type);
if (meanTimeToScan > slaTarget) {
await alertingApi.createAlert({
type: 'sla-breach',
message: `Scan frequency SLA breach for ${data.scan.type}`,
current: meanTimeToScan,
target: slaTarget
});
}
// Generate executive report
if (data.scan.type === 'compliance') {
await reportingApi.generateReport({
type: 'executive-compliance',
data: {
score: data.summary.compliance_score,
criticalFindings: data.summary.vulnerabilities_found.critical,
trend: await calculateTrend('compliance_score', 30)
},
recipients: ['ciso@company.com', 'compliance@company.com']
});
}
break;
case 'vulnerability:remediated':
// Track remediation metrics
await metricsDb.remediations.create({
vulnerabilityId: data.vulnerability_id,
timeToRemediate: data.time_to_remediate,
method: data.remediation.method,
automated: data.remediation.applied_by.type === 'automated'
});
// Update MTTR metrics
const mttr = await calculateMTTR(data.vulnerability_id);
await dashboardApi.updateMetric('mttr', mttr);
break;
}
res.status(200).json({ status: 'tracked' });
});
Need Help?
For webhook-related support: