Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Deploy Nozomi Networks Guardian sensors for passive OT network traffic analysis to achieve comprehensive asset visibility, real-time threat detection, and vulnerability assessment across industrial control systems without disrupting operations, leveraging behavioral anomaly detection and protocol-aware monitoring.
.claude/skills/implementing-ot-network-traffic-analysis-with-nozomi/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
| case-07 | ✗→✓ | ▲ Improved | — | — |
| case-14 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
Do not use for active vulnerability scanning of OT devices (see performing-ot-vulnerability-scanning-safely), for environments standardized on Dragos (see implementing-dragos-platform-for-ot-monitoring), or for IT-only network monitoring.
python#!/usr/bin/env python3 """Nozomi Guardian Deployment Manager and Alert Analyzer. Manages Nozomi Guardian sensor deployment validation, asset inventory extraction, and threat alert analysis for OT environments. """ import json import sys from collections import defaultdict from datetime import datetime from typing import Dict, List, Optional try: import requests except ImportError: print("Install requests: pip install requests") sys.exit(1) class NozomiGuardianManager: """Manages Nozomi Networks Guardian for OT monitoring.""" def __init__(self, guardian_url: str, api_token: str, verify_ssl: bool = False): self.guardian_url = guardian_url.rstrip("/") self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {api_token}", "Content-Type": "application/json", }) self.session.verify = verify_ssl def get_nodes(self, node_type: Optional[str] = None) -> List[Dict]: """Retrieve discovered network nodes (assets).""" params = {} if node_type: params["type"] = node_type resp = self.session.get(f"{self.guardian_url}/api/v1/nodes", params=params) resp.raise_for_status() return resp.json().get("result", []) def get_alerts(self, severity: str = "high", limit: int = 100) -> List[Dict]: """Retrieve security alerts.""" params = {"severity": severity, "limit": limit, "status": "open"} resp = self.session.get(f"{self.guardian_url}/api/v1/alerts", params=params) resp.raise_for_status() return resp.json().get("result", []) def get_links(self) -> List[Dict]: """Retrieve communication links between nodes.""" resp = self.session.get(f"{self.guardian_url}/api/v1/links") resp.raise_for_status() return resp.json().get("result", []) def get_vulnerabilities(self) -> List[Dict]: """Retrieve detected vulnerabilities.""" resp = self.session.get(f"{self.guardian_url}/api/v1/vulnerabilities") resp.raise_for_status() return resp.json().get("result", []) def validate_deployment(self): """Validate Guardian sensor deployment and coverage.""" print(f"\n{'='*65}") print("NOZOMI GUARDIAN DEPLOYMENT VALIDATION") print(f"{'='*65}") print(f"Guardian URL: {self.guardian_url}") print(f"Validation Time: {datetime.now().isoformat()}") # Check system status try: resp = self.session.get(f"{self.guardian_url}/api/v1/system/status") if resp.status_code == 200: status = resp.json() print(f"\n--- SYSTEM STATUS ---") print(f" Version: {status.get('version', 'N/A')}") print(f" Uptime: {status.get('uptime', 'N/A')}") print(f" Packets Processed: {status.get('packets_processed', 'N/A')}") print(f" Threat Intelligence: {status.get('threat_intelligence_version', 'N/A')}") except requests.RequestException as e: print(f" [!] System status unavailable: {e}") # Asset discovery summary nodes = self.get_nodes() print(f"\n--- ASSET DISCOVERY ---") print(f" Total Nodes Discovered: {len(nodes)}") type_counts = defaultdict(int) vendor_counts = defaultdict(int) protocol_set = set() for node in nodes: type_counts[node.get("type", "unknown")] += 1 vendor_counts[node.get("vendor", "Unknown")] += 1 for proto in node.get("protocols", []): protocol_set.add(proto) print(f"\n By Type:") for ntype, count in sorted(type_counts.items(), key=lambda x: -x[1]): print(f" {ntype}: {count}") print(f"\n By Vendor:") for vendor, count in sorted(vendor_counts.items(), key=lambda x: -x[1])[:10]: print(f" {vendor}: {count}") print(f"\n Protocols Observed: {', '.join(sorted(protocol_set))}") # Alert summary alerts = self.get_alerts(severity="high") print(f"\n--- ALERT SUMMARY ---") print(f" High/Critical Alerts: {len(alerts)}") alert_types = defaultdict(int) for alert in alerts: alert_types[alert.get("type_id", "unknown")] += 1 for atype, count in sorted(alert_types.items(), key=lambda x: -x[1])[:10]: print(f" {atype}: {count}") # Vulnerability summary vulns = self.get_vulnerabilities() print(f"\n--- VULNERABILITY SUMMARY ---") print(f" Total Vulnerabilities: {len(vulns)}") sev_counts = defaultdict(int) for vuln in vulns: sev_counts[vuln.get("severity", "unknown")] += 1 for sev in ["critical", "high", "medium", "low"]: if sev in sev_counts: print(f" {sev.capitalize()}: {sev_counts[sev]}") def analyze_communication_patterns(self): """Analyze OT communication patterns for anomalies.""" links = self.get_links() nodes = {n.get("id"): n for n in self.get_nodes()} print(f"\n--- COMMUNICATION ANALYSIS ---") print(f" Total Communication Links: {len(links)}") # Identify cross-zone communications cross_zone = [] for link in links: src_node = nodes.get(link.get("source_id"), {}) dst_node = nodes.get(link.get("destination_id"), {}) src_zone = src_node.get("zone", "unknown") dst_zone = dst_node.get("zone", "unknown") if src_zone != dst_zone and src_zone != "unknown" and dst_zone != "unknown": cross_zone.append({ "source": src_node.get("label", "Unknown"), "source_zone": src_zone, "destination": dst_node.get("label", "Unknown"), "dest_zone": dst_zone, "protocols": link.get("protocols", []), }) if cross_zone: print(f"\n Cross-Zone Communications: {len(cross_zone)}") for comm in cross_zone[:10]: print(f" {comm['source']} ({comm['source_zone']}) -> " f"{comm['destination']} ({comm['dest_zone']}) " f"via {', '.join(comm['protocols'])}") if __name__ == "__main__": manager = NozomiGuardianManager( guardian_url="https://nozomi-guardian.plant.local", api_token="your-api-token", ) manager.validate_deployment() manager.analyze_communication_patterns()
| Term | Definition | |------|------------| | Guardian | Nozomi Networks passive sensor that monitors OT network traffic via SPAN/TAP without generating additional traffic | | Vantage | Nozomi cloud-based central management platform for aggregating data across multiple Guardian sensors | | Behavioral Anomaly Detection (BAD) | Nozomi's AI-driven approach to detecting deviations from learned normal OT network behavior | | Smart Polling | Nozomi's active query feature using native protocols to safely extract additional device details | | Asset Intelligence | Nozomi's automatic identification and classification of OT/IoT assets from network traffic | | Threat Intelligence Feed | Nozomi Labs-maintained feed of OT-specific threat indicators, updated based on global honeypot data |
NOZOMI GUARDIAN OT MONITORING REPORT
=======================================
Site: [site name]
Date: YYYY-MM-DD
ASSET VISIBILITY:
Total Assets: [count]
PLCs: [count] | HMIs: [count] | Switches: [count]
Protocols: [list]
Vendors: [top 5]
THREAT DETECTION:
Critical Alerts: [count]
High Alerts: [count]
Top Alert Categories: [list]
VULNERABILITIES:
Critical: [count]
High: [count]
NETWORK ANALYSIS:
Communication Links: [count]
Cross-Zone Flows: [count]| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +32 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.