Autonomous Vehicle Safety: Sensors, AI & Cybersecurity

At UDHY – you’ll learn how sensors, AI, and cybersecurity shape the future of autonomous vehicle safety.

Home  ›  AI Courses  ›  AI for Expert Learners  › Autonomous Vehicle Safety: Sensors, AI & Cybersecurity

In this course, you will learn: Autonomous Vehicle Safety: Sensors, AI & Cybersecurity.

⏱ 14–18 hours · Self-paced 📋 5 modules 💻 4 code projects ✅ Free at UDHY.com

Prerequisites:

TL;DR — Quick Insights

  • Upstream Security documented 494 automotive and robot cyber incidents in 2025 — 92% conducted remotely, 44% involving ransomware. Every connected robot fleet is a potential attack surface.
  • Physical AI systems create a new attack surface that bridges digital and physical domains — a compromised robot does not just lose data, it can injure people and destroy equipment.
  • SROS2 (Secure Robot Operating System 2) provides the cryptographic foundation for ROS 2 fleet security — DDS-Security with per-robot X.509 certificates, access control, and encrypted communication.
  • The NIST Cybersecurity Framework provides the strategic structure: Identify → Protect → Detect → Respond → Recover. This course maps each NIST function to concrete robotics implementation.
  • By the end of this course you will configure a fully secured SROS2 fleet with certificate-based authentication, topic-level access control, and an intrusion detection system tailored for robot behaviour patterns.

Introduction

I have been in this industry for more than a decade — co-founding Moovita, Singapore’s first autonomous vehicle company, and spending years as a Principal Research Scientist at A*STAR. When I started building autonomous systems, cybersecurity was a secondary concern — the systems were not connected enough to be attractive targets. That era is definitively over.

In 2025, Upstream Security documented 494 cyber incidents targeting automotive and autonomous vehicle systems — 92% conducted entirely remotely, 44% involving ransomware. Amazon’s robot fleets, Waymo’s autonomous vehicles, and hospital surgical robots are all connected systems operating on public and private networks. When an attacker compromises a software system, they get data. When they compromise a robot fleet, they can stop production lines, redirect autonomous delivery vehicles, or — in the worst case — cause physical harm to people in the workspace.

This is the course that ties together everything you have built in the UDHY expert series. The Physical AI systems and multi-agent fleets from the previous two courses represent extraordinary capabilities — and extraordinary attack surfaces. This course teaches you to protect them.


Module 1: The Robot Threat Landscape in 2026

1.1 Why Robot Cybersecurity Is Fundamentally Different

Software cybersecurity protects data. Robot cybersecurity protects both data and physical systems — and the consequences of failure in the physical domain are categorically more severe.

The CIA triad in robotics:

  • Confidentiality: Proprietary sensor data, operational routes, manipulation sequences, and fleet telemetry are valuable intellectual property. A competitor who can read your robot’s sensor streams gains significant operational intelligence.
  • Integrity: A robot acting on falsified sensor data or tampered commands may perform actions its operators did not authorise. False sensor injection — feeding corrupted LiDAR or camera data to a robot — can cause it to “see” obstacles that do not exist or fail to see ones that do.
  • Availability: Ransomware that freezes a warehouse robot fleet stops production. A DDoS attack on the fleet management network leaves 200 robots unable to receive task assignments. Availability failures in robotics translate directly to operational downtime and financial losses.

What makes robots uniquely vulnerable:

Attack surface breadth: A robot fleet combines WiFi, Bluetooth, LiDAR, camera, GPS, cellular, and proprietary robot communication protocols — each a potential entry point. Classical IT systems have well-defined network perimeters; robot systems have none.

Physical consequences: A compromised robot can cause physical harm — a manipulator arm commanded to strike at full speed, a delivery robot instructed to drive into pedestrian traffic, a surgical robot receiving falsified force feedback. No enterprise server can injure someone.

Real-time constraints: Security measures that add 200ms of latency are acceptable for web applications. For a robot arm, 200ms of additional latency in the control loop can mean the difference between safe operation and collision. Security and real-time performance are in fundamental tension in robotics.

Legacy integration: Production robot fleets often include robots from multiple vendors, some with decade-old firmware and no security update mechanism. A single unpatched robot is a gateway to the entire fleet network.

1.2 The 2025–2026 Threat Landscape

Upstream Security’s 2025 automotive cyber report provides the most authoritative picture of real attacks on autonomous systems:

  • 494 incidents documented in 2025 — a 35% increase from 2024
  • 92% remote attacks — attackers do not need physical access
  • 44% ransomware — encrypting robot control systems for extortion
  • Most exploited vector: Telematics and remote fleet management APIs
  • Fastest-growing threat: Supply chain attacks targeting robot software update mechanisms

For robot fleets specifically, the five most critical attack vectors are:

1. ROS 2 Topic Eavesdropping: Without SROS2 enabled, all ROS 2 topic traffic is transmitted in plaintext over UDP multicast. An attacker on the same network segment can subscribe to any topic — including camera feeds, robot positions, and control commands — without authentication.

2. Man-in-the-Middle on Control Channels: An attacker who can intercept control messages between the fleet manager and individual robots can replay old commands, inject false commands, or prevent valid commands from reaching their target.

3. Sensor Spoofing: Physical attacks on sensors — LiDAR blinding with laser pulses, GPS spoofing, camera adversarial attacks — can manipulate what a robot perceives without touching its software. We covered the LiDAR spoofing defence from a perception perspective in Why Self-Driving Cars Still Fail; this course addresses it from the security architecture perspective.

4. VLA Model Adversarial Attacks: Physical AI systems using VLA models are vulnerable to adversarial inputs — carefully crafted physical objects or visual patterns that cause the model to misclassify or mistaken actions. A sticker placed strategically on a warehouse shelf could cause a robot’s VLA model to misidentify the object and perform an incorrect manipulation. This directly extends the adversarial stop sign problem covered in UDHY’s edge case analysis.

5. Fleet Management API Exploitation: The REST APIs and message queues used by fleet orchestration systems (covered in Course 2) are standard web endpoints with standard web vulnerabilities — SQL injection, broken authentication, insecure direct object references. Exploiting the fleet manager is more efficient than attacking individual robots.

Think about it: Your company operates 150 autonomous mobile robots in a pharmaceutical manufacturing facility. Map the complete attack surface — every system, interface, and protocol that an attacker could potentially exploit. Which three attack vectors would you prioritise for immediate hardening and why?


Module 2: The NIST Cybersecurity Framework for Robotics

2.1 NIST CSF 2.0 Applied to Robot Fleets

The NIST Cybersecurity Framework (CSF) 2.0 provides a structured approach to cybersecurity that maps directly onto robot fleet security requirements. The five functions — Identify, Protect, Detect, Respond, Recover — provide the strategic skeleton; this course fills in the robotics-specific implementation.

GOVERN (new in CSF 2.0): Establish cybersecurity policy, roles, and accountability across the robot fleet programme. Who is responsible for robot security updates? What is the patch deployment process? What constitutes an acceptable security incident? These governance questions must be answered before technical controls are implemented. For robot fleets operating in regulated industries (medical, pharmaceutical, aerospace), NIST CSF alignment is increasingly a contractual requirement.

IDENTIFY: Asset inventory of every robot, every network interface, every software component. A fleet you cannot enumerate is a fleet you cannot protect.

PROTECT: Technical controls that prevent attacks — SROS2 encryption, access control, network segmentation, software signing, physical security of robot hardware.

DETECT: Monitoring systems that identify attacks in progress — intrusion detection for robot behaviour anomalies, network traffic analysis, log aggregation, and alerting.

RESPOND: Incident response procedures for robot-specific scenarios — isolating a compromised robot from the fleet, emergency stopping affected systems, forensic data collection from robot logs.

RECOVER: Restoring fleet operations after an incident — clean re-imaging of compromised robots, validating restored system integrity, and post-incident review.

2.2 Robot Asset Inventory — The Foundation of Fleet Security

python

# Robot Fleet Asset Inventory Manager
# NIST CSF IDENTIFY function — you cannot protect what you cannot see

import json
import hashlib
import datetime
from dataclasses import dataclass, field, asdict
from typing import List, Dict, Optional

@dataclass
class RobotAsset:
    """Complete asset record for a single robot in the fleet"""
    robot_id: str
    manufacturer: str
    model: str
    firmware_version: str
    ros_distro: str                    # e.g. "jazzy"
    os_version: str                    # e.g. "Ubuntu 24.04 LTS"
    ip_address: str
    mac_address: str
    network_interfaces: List[str]      # ["WiFi", "Ethernet", "Bluetooth"]
    installed_packages: List[str]      # ROS 2 packages + system packages
    open_ports: List[int]
    last_security_scan: str
    certificate_expiry: str            # SROS2 certificate expiry date
    known_vulnerabilities: List[str]   # CVE IDs
    criticality: str                   # "high", "medium", "low"
    location: str                      # Physical location in facility

    def asset_fingerprint(self) -> str:
        """Unique fingerprint for change detection"""
        stable_data = f"{self.firmware_version}{self.installed_packages}{self.open_ports}"
        return hashlib.sha256(stable_data.encode()).hexdigest()[:16]

    def days_until_cert_expiry(self) -> int:
        expiry = datetime.datetime.strptime(self.certificate_expiry, "%Y-%m-%d")
        return (expiry - datetime.datetime.now()).days

    def security_risk_score(self) -> int:
        """Calculate security risk score 0-100 (higher = more risk)"""
        score = 0
        score += len(self.known_vulnerabilities) * 15    # Each CVE adds 15 points
        score += max(0, 10 - len(self.open_ports)) * 0  # Open ports add risk
        score += len(self.open_ports) * 5               # Each open port = 5 points
        if self.days_until_cert_expiry() < 30:
            score += 25                                  # Expiring cert = high risk
        if "Bluetooth" in self.network_interfaces:
            score += 10                                  # Bluetooth = attack surface
        if self.criticality == "high":
            score = int(score * 1.5)                    # Critical robots weighted higher
        return min(score, 100)


class FleetAssetRegistry:
    """
    Centralised asset inventory for robot fleet security management
    NIST CSF IDENTIFY function implementation
    """

    def __init__(self):
        self.assets: Dict[str, RobotAsset] = {}
        self.change_log: List[dict] = []

    def register_asset(self, asset: RobotAsset):
        """Register a new robot asset"""
        if asset.robot_id in self.assets:
            old_fingerprint = self.assets[asset.robot_id].asset_fingerprint()
            new_fingerprint = asset.asset_fingerprint()
            if old_fingerprint != new_fingerprint:
                self.change_log.append({
                    "timestamp": datetime.datetime.now().isoformat(),
                    "robot_id": asset.robot_id,
                    "change_type": "asset_modified",
                    "old_fingerprint": old_fingerprint,
                    "new_fingerprint": new_fingerprint
                })
                print(f"⚠️  Asset change detected: {asset.robot_id} "
                      f"(fingerprint: {old_fingerprint} → {new_fingerprint})")
        self.assets[asset.robot_id] = asset

    def security_audit(self):
        """Run fleet-wide security audit — NIST IDENTIFY function"""
        print("\n" + "="*65)
        print("ROBOT FLEET SECURITY AUDIT REPORT")
        print(f"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}")
        print("="*65)

        critical_issues = []
        warnings = []

        for robot_id, asset in self.assets.items():
            risk_score = asset.security_risk_score()

            print(f"\n📋 {robot_id} | {asset.manufacturer} {asset.model}")
            print(f"   Firmware: {asset.firmware_version} | OS: {asset.os_version}")
            print(f"   IP: {asset.ip_address} | Interfaces: {', '.join(asset.network_interfaces)}")
            print(f"   Open ports: {asset.open_ports}")
            print(f"   Risk score: {risk_score}/100 | Criticality: {asset.criticality}")

            # Flag issues
            if asset.known_vulnerabilities:
                issue = f"{robot_id}: {len(asset.known_vulnerabilities)} unpatched CVE(s): {asset.known_vulnerabilities}"
                critical_issues.append(issue)
                print(f"   🔴 CRITICAL: Unpatched vulnerabilities: {asset.known_vulnerabilities}")

            cert_days = asset.days_until_cert_expiry()
            if cert_days < 30:
                warning = f"{robot_id}: SROS2 certificate expires in {cert_days} days"
                warnings.append(warning)
                print(f"   🟡 WARNING: Certificate expires in {cert_days} days")

            if len(asset.open_ports) > 3:
                warnings.append(f"{robot_id}: {len(asset.open_ports)} open ports — reduce attack surface")
                print(f"   🟡 WARNING: Excessive open ports ({len(asset.open_ports)})")

        print(f"\n{'='*65}")
        print(f"SUMMARY: {len(self.assets)} robots audited")
        print(f"Critical issues: {len(critical_issues)}")
        print(f"Warnings: {len(warnings)}")
        if critical_issues:
            print("\nCRITICAL ACTIONS REQUIRED:")
            for issue in critical_issues:
                print(f"  🔴 {issue}")

    def export_inventory(self, filepath: str):
        """Export complete asset inventory as JSON for NIST compliance documentation"""
        inventory = {
            "export_timestamp": datetime.datetime.now().isoformat(),
            "total_assets": len(self.assets),
            "assets": [asdict(a) for a in self.assets.values()],
            "change_log": self.change_log
        }
        with open(filepath, "w") as f:
            json.dump(inventory, f, indent=2)
        print(f"Asset inventory exported to {filepath}")


# Sample fleet inventory
registry = FleetAssetRegistry()

sample_robots = [
    RobotAsset(
        robot_id="AMR-01",
        manufacturer="MiR", model="MiR250",
        firmware_version="2.13.4", ros_distro="jazzy",
        os_version="Ubuntu 24.04 LTS",
        ip_address="192.168.10.101", mac_address="AA:BB:CC:01:02:03",
        network_interfaces=["WiFi", "Ethernet"],
        installed_packages=["nav2", "slam_toolbox", "robot_state_publisher"],
        open_ports=[22, 80, 9090],
        last_security_scan="2026-05-01",
        certificate_expiry="2026-12-31",
        known_vulnerabilities=[],
        criticality="high",
        location="Warehouse Zone A"
    ),
    RobotAsset(
        robot_id="ARM-02",
        manufacturer="Universal Robots", model="UR10e",
        firmware_version="5.11.8", ros_distro="jazzy",
        os_version="Ubuntu 24.04 LTS",
        ip_address="192.168.10.110", mac_address="AA:BB:CC:02:03:04",
        network_interfaces=["Ethernet", "Bluetooth"],
        installed_packages=["ur_robot_driver", "moveit2", "gripper_controller"],
        open_ports=[22, 502, 4840, 80, 443, 8080],   # Modbus, OPC-UA, HTTP, HTTPS, alt-HTTP
        last_security_scan="2026-03-15",
        certificate_expiry="2026-06-01",              # Expiring soon!
        known_vulnerabilities=["CVE-2025-1234"],      # Known unpatched CVE
        criticality="high",
        location="Assembly Line 3"
    ),
]

for robot in sample_robots:
    registry.register_asset(robot)

registry.security_audit()
registry.export_inventory("fleet_security_inventory.json")

Module 3: SROS2 — Securing ROS 2 Communication

3.1 Why Default ROS 2 Is Insecure

By default, ROS 2 uses DDS (Data Distribution Service) without security extensions. All topic data is transmitted as plaintext UDP multicast on the local network. Any device on the same network segment can:

  • Subscribe to any topic (including camera feeds, robot positions, and control commands)
  • Publish to any topic (including robot velocity commands and emergency stop topics)
  • Discover all nodes and services on the network

In a development environment, this openness is convenient. In production, it is a critical vulnerability. SROS2 (Secure ROS 2) adds DDS-Security — the OMG standard security extension for DDS — providing encryption, authentication, and access control for all ROS 2 communication.

3.2 SROS2 Setup and Certificate Management

bash

# ─────────────────────────────────────────────
# SROS2 Complete Setup Guide for Robot Fleet
# Ubuntu 24 + ROS 2 Jazzy Jalisco
# ─────────────────────────────────────────────

# Step 1: Install SROS2 tools
sudo apt install ros-jazzy-sros2
source /opt/ros/jazzy/setup.bash

# Step 2: Create fleet security keystore
# This is the root Certificate Authority (CA) for your fleet
ros2 security create_keystore /fleet_security/keystore
# Creates: /fleet_security/keystore/public/
#          /fleet_security/keystore/private/
#          /fleet_security/keystore/ca.cert.pem  ← Root CA certificate

# Step 3: Create identity certificates for each robot
# Each robot gets its own X.509 certificate signed by the fleet CA
ros2 security create_key /fleet_security/keystore /AMR_01
ros2 security create_key /fleet_security/keystore /AMR_02
ros2 security create_key /fleet_security/keystore /DRONE_01
ros2 security create_key /fleet_security/keystore /ARM_01
ros2 security create_key /fleet_security/keystore /fleet_manager

# Each key directory contains:
# identity_cert.pem        — robot's X.509 certificate
# identity_key.pem         — robot's private key (NEVER share this)
# permissions.xml          — what topics this robot can pub/sub
# permissions.p7s          — CA-signed permissions (tamper-evident)
# governance.p7s           — fleet-wide security policy

echo "Keystore created. Deploy identity credentials to each robot securely."

3.3 Access Control Policy — Topic-Level Permissions

SROS2 allows granular control over which robot can publish or subscribe to which topics. This implements the principle of least privilege — each robot has access only to the topics it genuinely needs:

xml

<!-- permissions.xml for AMR-01 transport robot -->
<!-- This robot can: navigate, report status, receive tasks -->
<!-- This robot CANNOT: publish to emergency_stop (prevents spoofing) -->

<?xml version="1.0" encoding="UTF-8"?>
<permissions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <grant name="AMR_01_permissions">
    <subject_name>CN=AMR_01,O=UDHY Fleet,C=SG</subject_name>
    <validity>
      <not_before>2026-01-01T00:00:00</not_before>
      <not_after>2027-01-01T00:00:00</not_after>
    </validity>
    <allow_rule>
      <domains><id>0</id></domains>
      <publish>
        <!-- AMR-01 can publish its own status and odometry -->
        <topics>
          <topic>/AMR_01/status</topic>
          <topic>/AMR_01/odom</topic>
          <topic>/AMR_01/scan</topic>
          <topic>/AMR_01/battery_state</topic>
          <topic>/fleet/robot_heartbeat</topic>
        </topics>
      </publish>
      <subscribe>
        <!-- AMR-01 can receive task assignments and navigation goals -->
        <topics>
          <topic>/fleet/task_assignments</topic>
          <topic>/AMR_01/goal_pose</topic>
          <topic>/AMR_01/cmd_vel</topic>
          <topic>/fleet/map_updates</topic>
          <topic>/fleet/emergency_stop</topic>  <!-- Can receive but NOT publish -->
        </topics>
      </subscribe>
    </allow_rule>
    <deny_rule>
      <!-- Explicitly deny publishing to fleet control topics -->
      <!-- Prevents a compromised AMR from spoofing fleet-wide commands -->
      <domains><id>0</id></domains>
      <publish>
        <topics>
          <topic>/fleet/emergency_stop</topic>
          <topic>/fleet/task_assignments</topic>
          <topic>/fleet/manager/*</topic>
        </topics>
      </publish>
    </deny_rule>
  </grant>
</permissions>

bash

# Sign the permissions with the fleet CA (tamper-evident)
ros2 security create_permission \
    /fleet_security/keystore \
    /AMR_01 \
    policies/AMR_01_policy.xml

# Launch ROS 2 node with SROS2 enabled
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce        # Reject nodes without valid credentials
export ROS_SECURITY_KEYSTORE=/fleet_security/keystore

ros2 run my_robot_pkg amr_node \
    --ros-args \
    --enclave /AMR_01

echo "AMR-01 now communicates with full DDS-Security:"
echo "  ✅ Encrypted: AES-256-GCM"
echo "  ✅ Authenticated: X.509 certificate"
echo "  ✅ Authorised: topic-level access control"
echo "  ✅ Integrity: HMAC message signing"

Module 4: Intrusion Detection for Robot Fleets

4.1 Robot Behaviour Anomaly Detection

Traditional network intrusion detection systems detect anomalies in packet timing, protocol violations, and unusual connection patterns. Robot fleets require an additional layer: behaviour anomaly detection — identifying when a robot is acting outside its expected operational parameters, which may indicate compromise or malfunction.

python

# Robot Behaviour Anomaly Detector
# Detects compromised robots through behavioural deviations
# NIST CSF DETECT function implementation

import numpy as np
from collections import deque
from dataclasses import dataclass
from typing import Dict, List, Tuple
import time

@dataclass
class RobotBehaviourProfile:
    """Statistical baseline of normal robot behaviour"""
    robot_id: str
    # Velocity statistics (mean, std) for normal operation
    linear_velocity_mean: float = 0.8    # m/s typical
    linear_velocity_std: float  = 0.3
    angular_velocity_mean: float = 0.2   # rad/s typical
    angular_velocity_std: float  = 0.15
    # Task completion statistics
    avg_task_duration: float = 180.0     # seconds
    task_duration_std: float  = 45.0
    # Network statistics
    avg_msg_frequency: float = 10.0     # Hz
    msg_frequency_std: float  = 2.0
    # Established by observing 30 days of normal operation
    baseline_established: bool = True

class RobotAnomalyDetector:
    """
    Statistical anomaly detection for robot fleet behaviour
    Uses Z-score analysis and sliding window statistics
    """

    def __init__(self, alert_threshold: float = 3.0):
        self.profiles: Dict[str, RobotBehaviourProfile] = {}
        self.observation_windows: Dict[str, deque] = {}
        self.alert_threshold = alert_threshold   # Standard deviations for alert
        self.active_alerts: List[dict] = []
        self.window_size = 100                   # Observations per sliding window

    def register_robot(self, profile: RobotBehaviourProfile):
        self.profiles[profile.robot_id] = profile
        self.observation_windows[profile.robot_id] = deque(maxlen=self.window_size)
        print(f"[IDS] Behaviour profile loaded for {profile.robot_id}")

    def z_score(self, value: float, mean: float, std: float) -> float:
        """Calculate Z-score (standard deviations from mean)"""
        if std == 0:
            return 0
        return abs((value - mean) / std)

    def analyse_observation(self, robot_id: str, observation: dict) -> List[str]:
        """
        Analyse a single robot observation for anomalies.
        Returns list of anomaly descriptions (empty = normal).
        """
        if robot_id not in self.profiles:
            return [f"Unknown robot {robot_id} — not in registry"]

        profile = self.profiles[robot_id]
        anomalies = []

        # Check linear velocity
        if "linear_velocity" in observation:
            z = self.z_score(observation["linear_velocity"],
                           profile.linear_velocity_mean,
                           profile.linear_velocity_std)
            if z > self.alert_threshold:
                anomalies.append(
                    f"VELOCITY_ANOMALY: linear_vel={observation['linear_velocity']:.2f}m/s "
                    f"(z={z:.1f}σ from baseline {profile.linear_velocity_mean:.1f}m/s)"
                )

        # Check angular velocity
        if "angular_velocity" in observation:
            z = self.z_score(observation["angular_velocity"],
                           profile.angular_velocity_mean,
                           profile.angular_velocity_std)
            if z > self.alert_threshold:
                anomalies.append(
                    f"SPIN_ANOMALY: angular_vel={observation['angular_velocity']:.2f}rad/s "
                    f"(z={z:.1f}σ)"
                )

        # Check message frequency
        if "msg_frequency" in observation:
            z = self.z_score(observation["msg_frequency"],
                           profile.avg_msg_frequency,
                           profile.msg_frequency_std)
            if z > self.alert_threshold:
                anomalies.append(
                    f"FREQUENCY_ANOMALY: {observation['msg_frequency']:.1f}Hz "
                    f"(z={z:.1f}σ) — possible replay attack or flooding"
                )

        # Check for impossible physics (instant position jump)
        if "position_jump_m" in observation:
            if observation["position_jump_m"] > 2.0:  # > 2m in one control cycle
                anomalies.append(
                    f"POSITION_TELEPORT: jumped {observation['position_jump_m']:.2f}m "
                    f"in one cycle — possible GPS/odometry spoofing"
                )

        # Log observation
        self.observation_windows[robot_id].append({
            "timestamp": time.time(),
            "observation": observation,
            "anomaly_count": len(anomalies)
        })

        return anomalies

    def process_fleet_tick(self, fleet_observations: Dict[str, dict]):
        """Process one observation tick for entire fleet"""
        for robot_id, obs in fleet_observations.items():
            anomalies = self.analyse_observation(robot_id, obs)

            if anomalies:
                alert = {
                    "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
                    "robot_id": robot_id,
                    "severity": "CRITICAL" if len(anomalies) > 1 else "WARNING",
                    "anomalies": anomalies
                }
                self.active_alerts.append(alert)

                severity_icon = "🔴" if alert["severity"] == "CRITICAL" else "🟡"
                print(f"\n{severity_icon} [{alert['timestamp']}] "
                      f"ANOMALY DETECTED: {robot_id}")
                for a in anomalies:
                    print(f"   → {a}")

    def incident_report(self):
        """Generate security incident report"""
        print(f"\n{'='*65}")
        print(f"INTRUSION DETECTION REPORT — {len(self.active_alerts)} alerts")
        print(f"{'='*65}")
        critical = [a for a in self.active_alerts if a["severity"] == "CRITICAL"]
        warnings  = [a for a in self.active_alerts if a["severity"] == "WARNING"]
        print(f"Critical: {len(critical)} | Warnings: {len(warnings)}")

        if critical:
            print("\nCRITICAL INCIDENTS — Immediate response required:")
            for alert in critical:
                print(f"  🔴 {alert['timestamp']} | {alert['robot_id']}")
                for a in alert["anomalies"]:
                    print(f"     {a}")


# Set up IDS for demo fleet
ids = RobotAnomalyDetector(alert_threshold=3.0)

profiles = [
    RobotBehaviourProfile("AMR-01", linear_velocity_mean=0.8, linear_velocity_std=0.2,
                          angular_velocity_mean=0.15, angular_velocity_std=0.1,
                          avg_msg_frequency=10.0, msg_frequency_std=1.5),
    RobotBehaviourProfile("ARM-01", linear_velocity_mean=0.0, linear_velocity_std=0.05,
                          angular_velocity_mean=0.3, angular_velocity_std=0.1,
                          avg_msg_frequency=50.0, msg_frequency_std=2.0),
]
for p in profiles:
    ids.register_robot(p)

# Simulate normal operation then attack
print("\n--- Normal operation (3 ticks) ---")
normal_ticks = [
    {"AMR-01": {"linear_velocity": 0.85, "angular_velocity": 0.12, "msg_frequency": 10.2}},
    {"AMR-01": {"linear_velocity": 0.79, "angular_velocity": 0.18, "msg_frequency": 9.8}},
    {"AMR-01": {"linear_velocity": 0.82, "angular_velocity": 0.14, "msg_frequency": 10.1}},
]
for tick in normal_ticks:
    ids.process_fleet_tick(tick)
print("   (No anomalies — normal operation confirmed)")

print("\n--- Simulated cyberattack ---")
attack_ticks = [
    # Attacker sends high-frequency spoofed velocity commands
    {"AMR-01": {"linear_velocity": 3.5, "angular_velocity": 4.2, "msg_frequency": 95.0,
                "position_jump_m": 5.2}},
    # Command injection causing uncharacteristic spinning
    {"AMR-01": {"linear_velocity": 0.1, "angular_velocity": 8.5, "msg_frequency": 12.0}},
]
for tick in attack_ticks:
    ids.process_fleet_tick(tick)

ids.incident_report()

Module 5: Incident Response and Recovery

5.1 Robot Incident Response Playbook

When a security incident is detected, the response must be both fast and correct — isolating the affected robot without cascading disruption to the rest of the fleet.

Immediate response (first 60 seconds):

python

class RobotIncidentResponse:
    """
    Automated incident response for robot fleet security events
    NIST CSF RESPOND function implementation
    """

    def __init__(self, fleet_manager, ids_system):
        self.fleet_manager = fleet_manager
        self.ids = ids_system
        self.quarantined_robots = set()
        self.incident_log = []

    def quarantine_robot(self, robot_id: str, reason: str):
        """
        Isolate a compromised robot from the fleet.
        Steps: (1) Emergency stop, (2) Network isolation, (3) Task reassignment
        """
        if robot_id in self.quarantined_robots:
            return  # Already quarantined

        print(f"\n🚨 INITIATING QUARANTINE: {robot_id}")
        print(f"   Reason: {reason}")

        # Step 1: Emergency stop
        print("   [1/4] Sending emergency stop command...")
        # In production: publish to /robot_id/cmd_vel with zero velocity
        # and set /robot_id/emergency_stop = True via SROS2 authenticated topic

        # Step 2: Revoke SROS2 certificate (immediate network isolation)
        print("   [2/4] Revoking SROS2 certificate...")
        print(f"         Updating CRL: adding {robot_id} certificate serial")
        print("         Pushing CRL update to all fleet nodes...")
        # In production: update Certificate Revocation List and push to fleet CA
        # All other robots reject messages from the revoked certificate immediately

        # Step 3: Network-level isolation
        print("   [3/4] Applying network ACL — blocking robot IP...")
        print(f"         iptables: DROP all traffic from 192.168.10.{robot_id[-2:]}")

        # Step 4: Reassign orphaned tasks
        print("   [4/4] Reassigning quarantined robot's tasks...")
        if robot_id in [r for r in self.fleet_manager.robots]:
            self.fleet_manager.report_robot_failure(robot_id, f"Security quarantine: {reason}")

        self.quarantined_robots.add(robot_id)
        incident = {
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            "robot_id": robot_id,
            "action": "QUARANTINE",
            "reason": reason,
            "status": "contained"
        }
        self.incident_log.append(incident)
        print(f"   ✅ {robot_id} quarantined successfully")

    def recovery_checklist(self, robot_id: str) -> List[str]:
        """
        Generate recovery checklist for restoring a quarantined robot
        NIST CSF RECOVER function
        """
        return [
            f"1. Physically retrieve {robot_id} and disconnect from network",
            "2. Image SD card / internal storage for forensic analysis",
            "3. Flash clean OS image from verified golden image",
            "4. Update all packages to latest verified versions",
            "5. Generate new SROS2 identity certificate (new private key)",
            "6. Apply updated security policy and permissions.xml",
            "7. Run vulnerability scan — verify no CVEs in installed packages",
            "8. Reconnect to isolated VLAN for integration testing",
            "9. Verify SROS2 encrypted communication with test fleet node",
            "10. Run 30-minute operational validation before returning to production",
            "11. Document incident and recovery in security log",
            "12. Update fleet asset registry with new firmware version and cert hash"
        ]

    def generate_incident_report(self) -> str:
        """Generate NIST-compliant incident report"""
        report = [
            "SECURITY INCIDENT REPORT",
            "="*50,
            f"Report generated: {time.strftime('%Y-%m-%d %H:%M:%S')}",
            f"Total incidents: {len(self.incident_log)}",
            f"Quarantined robots: {list(self.quarantined_robots)}",
            "",
            "INCIDENT LOG:",
        ]
        for incident in self.incident_log:
            report.append(f"  [{incident['timestamp']}] {incident['robot_id']}: "
                         f"{incident['action']} — {incident['reason']}")
        return "\n".join(report)

What You Have Learned

By completing this course you can now:

  • Map the complete attack surface of a connected robot fleet across all layers
  • Apply the NIST CSF 2.0 framework to robot fleet security programme design
  • Configure SROS2 with certificate-based authentication and topic-level access control
  • Build a fleet asset inventory system for NIST IDENTIFY compliance
  • Implement behaviour anomaly detection for real-time intrusion detection
  • Execute an incident response procedure that isolates compromised robots without disrupting fleet operations

You have now completed the UDHY Expert AI for Robotics trilogy. Your next step is applying these skills in production — beginning with UDHY’s Expert Robotics Course for hands-on VLA model deployment on real hardware.


FAQ


References

  1. Upstream Security. (2025). Automotive Cyber Incident Report 2025: 494 Incidents, 92% Remote. upstream.auto
  2. NIST. (2024). Cybersecurity Framework 2.0. nist.gov
  3. OMG. (2018). DDS Security Standard v1.1. omg.org
  4. CodeRed. (2025). Cybersecurity for Robotics and Autonomous Systems Course. coderedpro.com
  5. Deloitte. (February 2026). Physical AI and Humanoid Robots — Cybersecurity Vulnerabilities. deloitte.com
  6. ROS 2 Security Working Group. (2026). SROS2 Documentation. docs.ros.org
  7. MentorCruise. (2026). Top 11 Robotics Certifications 2026 — Cybersecurity Track. mentorcruise.com
  8. EU AI Act. (2024). Regulation on Artificial Intelligence — Annex III High-Risk AI. eur-lex.europa.eu

Designed by Dr. Dilip Kumar Limbu — Former Principal Research Scientist, A*STAR · Co-Founder, Moovita, Singapore’s first autonomous vehicle company · 30 years building real-world autonomous systems. UDHY.com.

Scroll to Top