| name | performing-ot-vulnerability-assessment-with-claroty |
| description | Perform OT vulnerability assessments using the Claroty xDome platform for asset discovery, risk scoring, and vulnerability correlation, combining passive traffic-based identification and active safe device querying with CVE/ICS-CERT advisory correlation for remediation prioritization. Use for scheduled IEC 62443 or NERC CIP OT vulnerability assessments, initial xDome deployment, or generating CIP-010-4 compliance evidence; not for active PLC scanning or penetration testing. |
| domain | cybersecurity |
| subdomain | ot-ics-security |
| tags | ["ot-security","ics","scada","industrial-control","iec62443","vulnerability-assessment","claroty"] |
| version | 1.0.0 |
| author | mahipal |
| license | Apache-2.0 |
| nist_csf | ["PR.IR-01","DE.CM-01","ID.AM-05","GV.OC-02"] |
| mitre_attack | ["T1078","T1190","T1059","T0816","T0836"] |
Performing OT Vulnerability Assessment with Claroty
When to Use
- When conducting scheduled OT vulnerability assessments per IEC 62443 or NERC CIP requirements
- When deploying Claroty xDome for the first time and performing initial asset discovery and risk assessment
- When correlating newly published ICS-CERT advisories against your OT asset inventory
- When prioritizing OT vulnerability remediation with limited maintenance windows
- When generating compliance evidence for CIP-010-4 vulnerability assessment requirements
Do not use for active vulnerability scanning of PLCs and safety systems (see performing-ot-network-security-assessment for passive approaches), for IT-only vulnerability management (see standard vulnerability scanners), or for penetration testing (see performing-ics-penetration-testing).
Prerequisites
- Claroty xDome or CTD (Continuous Threat Detection) deployed with sensors on OT network
- Network SPAN/TAP access for passive asset discovery
- CISA ICS-CERT advisory subscription for vulnerability tracking
- Asset inventory with firmware versions for all OT devices
- Change management process for patch deployment during maintenance windows
Workflow
Step 1: Configure Asset Discovery and Vulnerability Correlation
Configure Claroty to perform passive and active-safe discovery to build complete asset inventory with firmware versions for vulnerability correlation.
"""OT Vulnerability Assessment Manager.
Correlates OT asset inventory with ICS-CERT advisories and CVE data
to identify, prioritize, and track OT vulnerabilities. Designed to
integrate with Claroty xDome API or standalone operation.
"""
import json
import sys
from collections import defaultdict
from dataclasses import dataclass, field, asdict
from datetime import datetime
import requests
@dataclass
class OTAsset:
asset_id: str
name: str
vendor: str
model: str
firmware_version:
asset_type:
purdue_level:
ip_address:
protocol:
criticality:
zone:
:
vuln_id:
cve_id:
title:
severity:
cvss_score:
affected_vendor:
affected_product:
affected_versions:
description:
ics_cert_advisory: =
remediation: =
patch_available: =
compensating_controls: =
:
asset: OTAsset
vulnerability: OTVulnerability
risk_score: =
risk_rating: =
exploitability: =
operational_impact: =
compensating_controls: = field(default_factory=)
remediation_priority: =
:
():
.assets = []
.vulnerabilities = []
.risk_assessments = []
():
a assets_data:
.assets.append(OTAsset(**a))
()
():
()
:
url =
resp = requests.get(url, timeout=)
resp.raise_for_status()
data = resp.json()
ics_vulns = []
vuln data.get(, []):
ics_vendors = [
, , , ,
, , , , ,
, , , ,
]
vendor = vuln.get(, ).lower()
(v vendor v ics_vendors):
ics_vulns.append(vuln)
()
ics_vulns
Exception e:
()
[]
():
()
asset .assets:
vuln .vulnerabilities:
(vuln.affected_vendor.lower() asset.vendor.lower()
vuln.affected_product.lower() asset.model.lower()):
ra = RiskAssessment(asset=asset, vulnerability=vuln)
._calculate_risk_score(ra)
.risk_assessments.append(ra)
()
():
base = ra.vulnerability.cvss_score
criticality_weights = {
: ,
: ,
: ,
: ,
}
criticality = criticality_weights.get(ra.asset.criticality, )
level_weights = {
: ,
: ,
: ,
: ,
: ,
}
level_factor = level_weights.get(ra.asset.purdue_level, )
comp_reduction = ra.compensating_controls
ra.risk_score = (base * criticality * level_factor * comp_reduction, )
ra.risk_score = (ra.risk_score, )
ra.risk_score >= :
ra.risk_rating =
ra.remediation_priority =
ra.risk_score >= :
ra.risk_rating =
ra.remediation_priority =
ra.risk_score >= :
ra.risk_rating =
ra.remediation_priority =
:
ra.risk_rating =
ra.remediation_priority =
():
sorted_ra = (.risk_assessments, key= x: -x.risk_score)
report = []
report.append( * )
report.append()
report.append()
report.append()
report.append()
report.append( * )
sev [, , , ]:
findings = [ra ra sorted_ra ra.risk_rating == sev]
findings:
report.append()
ra findings[:]:
report.append()
report.append()
report.append()
report.append()
report.append()
ra.vulnerability.patch_available:
report.append()
:
report.append()
.join(report)
():
data = {
: datetime.now().isoformat(),
: (.assets),
: (.vulnerabilities),
: [
{
: ra.asset.name,
: ra.asset.ip_address,
: ra.vulnerability.cve_id,
: ra.risk_score,
: ra.risk_rating,
: ra.remediation_priority,
}
ra (.risk_assessments, key= x: -x.risk_score)
],
}
(output_file, ) f:
json.dump(data, f, indent=)
__name__ == :
assessment = OTVulnerabilityAssessment()
advisories = assessment.fetch_ics_advisories()
()