Install
$ agentstack add skill-arpitg1304-robotics-agent-skills-robotics-security Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged2 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
- high Destructive filesystem operation.
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Robotics Security Skill
When to Use This Skill
- Enabling SROS2 encryption and access control on ROS2 topics/services
- Generating keystores, certificates, and security policies for DDS
- Hardening robot onboard computers (SSH, firewalls, minimal packages)
- Setting up network segmentation between robot control/data/management planes
- Managing secrets and credentials across a robot fleet
- Securing Docker containers running ROS2 nodes
- Designing e-stop and safety systems that survive cyber compromise
- Auditing a robot system for security vulnerabilities
- Implementing secure boot and firmware verification
- Addressing IEC 62443 requirements for industrial robot deployments
The Robot Attack Surface
Robots are unique: cyber vulnerabilities become physical threats.
NETWORK MIDDLEWARE APPLICATION
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Open DDS ports │───────▶│ Unauthenticated│──────────▶│ Hardcoded │
│ (7400-7500) │ │ /cmd_vel pub │ │ credentials │
│ Unsegmented LAN│ │ No msg signing │ │ Unvalidated cmd│
└────────────────┘ └────────────────┘ └────────────────┘
PHYSICAL FIRMWARE SUPPLY CHAIN
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ USB/debug ports│───────▶│ Unsigned │──────────▶│ Compromised │
│ Serial consoles│ │ firmware OTA │ │ ROS packages │
│ Exposed SBCs │ │ No secure boot │ │ Unverified imgs│
└────────────────┘ └────────────────┘ └────────────────┘
| Vector | Impact | |--------|--------| | Unauthenticated /cmd_vel | Robot moves unexpectedly — injury/damage | | Sensor spoofing (/scan, /camera/image) | Robot collides, wrong decisions | | Open DDS multicast discovery | Full topic graph enumeration by passive listener | | USB/serial physical access | Root shell, firmware flash, data exfiltration | | Unsigned firmware update | Persistent backdoor in motor controllers |
SROS2: DDS Security
SROS2 wraps DDS Security to provide authentication, encryption, and access control at the DDS layer.
Keystore Generation and Certificate Setup
export ROS_SECURITY_KEYSTORE=~/sros2_keystore
ros2 security create_keystore ${ROS_SECURITY_KEYSTORE}
# Generate per-node enclaves (use exact fully-qualified node names)
ros2 security create_enclave ${ROS_SECURITY_KEYSTORE} /my_robot/camera_driver
ros2 security create_enclave ${ROS_SECURITY_KEYSTORE} /my_robot/navigation
ros2 security create_enclave ${ROS_SECURITY_KEYSTORE} /my_robot/motor_controller
ros2 security create_enclave ${ROS_SECURITY_KEYSTORE} /my_robot/teleop
# Result:
# sros2_keystore/
# ├── enclaves/my_robot/{camera_driver,navigation,...}/
# │ ├── cert.pem, key.pem # Node identity
# │ ├── governance.p7s # Signed governance
# │ └── permissions.p7s # Signed permissions
# ├── public/ca.cert.pem # CA certificate
# └── private/ca.key.pem # CA private key — PROTECT THIS
Security Policy XML
Governance — domain-wide security behavior:
0230
false
true
ENCRYPT
ENCRYPT
ENCRYPT
*
true
true
true
ENCRYPT
ENCRYPT
Permissions — per-enclave publish/subscribe rules:
CN=/my_robot/motor_controller
2024-01-01T00:00:00
2026-01-01T00:00:00
0
rt/joint_states
rt/cmd_vel
DENY
CN=/my_robot/teleop
2024-01-01T00:00:00
2026-01-01T00:00:00
0
rt/cmd_vel
rt/joy
DENY
Enabling Security in Launch Files
import os
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
security_env = {
'ROS_SECURITY_KEYSTORE': os.path.expanduser('~/sros2_keystore'),
'ROS_SECURITY_ENABLE': 'true',
'ROS_SECURITY_STRATEGY': 'Enforce', # Enforce=reject unauth, Permissive=warn only
}
return LaunchDescription([
Node(package='my_robot_drivers', executable='motor_controller',
name='motor_controller', namespace='my_robot',
additional_env=security_env),
Node(package='my_robot_nav', executable='navigation',
name='navigation', namespace='my_robot',
additional_env=security_env),
])
Always use Enforce in production. Permissive logs violations but allows them — debugging aid only.
Per-Topic Access Control
Design with least privilege:
| Node | Publishes | Subscribes | Rationale | |------|-----------|------------|-----------| | motor_controller | /joint_states | /cmd_vel | Driver acts on velocity only | | navigation | /cmd_vel, /path | /scan, /odom, /map | Nav reads sensors, writes commands | | camera_driver | /camera/image_raw | (none) | Pure source — no subscriptions | | teleop | /cmd_vel | /joy | Joystick passthrough — minimal surface |
A compromised camera_driver cannot publish to /cmd_vel — permissions deny it at the DDS layer.
Network Hardening
Network Segmentation
┌───────────────────┬──────────────────┬────────────────────────┐
│ CONTROL PLANE │ DATA PLANE │ MANAGEMENT PLANE │
│ VLAN 10 │ VLAN 20 │ VLAN 30 │
│ 10.10.10.0/24 │ 10.10.20.0/24 │ 10.10.30.0/24 │
├───────────────────┼──────────────────┼────────────────────────┤
│ /cmd_vel, /odom │ /camera/image │ SSH, Prometheus │
│ /joint_states │ /pointcloud │ Log collection │
│ /e_stop │ /map, /rosbag │ Fleet mgmt API │
├───────────────────┼──────────────────┼────────────────────────┤
│ LOW LATENCY │ HIGH BANDWIDTH │ RESTRICTED ACCESS │
│ QoS: RELIABLE │ QoS: BEST_EFFORT │ Jump host / VPN + 2FA │
└───────────────────┴──────────────────┴────────────────────────┘
Management plane is never reachable from data plane. Control plane traffic never transits WiFi.
Firewall Rules for ROS2/DDS
#!/bin/bash
# firewall_ros2.sh — adapt interface names to your hardware
iptables -F && iptables -X
# Default: drop inbound, allow outbound
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT # Loopback (intra-process DDS)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Existing connections
iptables -A INPUT -p udp --dport 7400:7500 -s 10.10.10.0/24 -j ACCEPT # DDS discovery — control VLAN
iptables -A INPUT -p udp --dport 7500:7700 -s 10.10.10.0/24 -j ACCEPT # DDS user traffic
iptables -A INPUT -p tcp --dport 22 -s 10.10.30.0/24 -j ACCEPT # SSH — mgmt VLAN only
iptables -A INPUT -i wlan0 -d 239.255.0.0/16 -j DROP # Block multicast on WiFi
iptables -A INPUT -j LOG --log-prefix "DROPPED: " --log-level 4
iptables -A INPUT -j DROP
iptables-save > /etc/iptables/rules.v4
VLAN Configuration for Robot Networks
# /etc/netplan/01-robot-vlans.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0: {dhcp4: false}
vlans:
vlan10:
id: 10
link: eth0
addresses: [10.10.10.5/24]
vlan20:
id: 20
link: eth0
addresses: [10.10.20.5/24]
vlan30:
id: 30
link: eth0
addresses: [10.10.30.5/24]
routes: [{to: default, via: 10.10.30.1}]
Disabling DDS Multicast in Production
Multicast auto-discovery exposes the full topic graph. Use unicast peer lists.
false
auto
export CYCLONEDDS_URI=file:///etc/ros2/cyclonedds_secure.xml
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
FastDDS equivalent — set initialPeersList with explicit unicast locators and omit multicast locators in the participant profile. Use FASTRTPS_DEFAULT_PROFILES_FILE env var to load.
SSH and Host Hardening
SSH Key-Only Auth, Disable Root Login
# /etc/ssh/sshd_config
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers robot-admin
X11Forwarding no
AllowTcpForwarding no
PermitTunnel no
sudo systemctl restart sshd
# Per-robot key pair (on management workstation)
ssh-keygen -t ed25519 -f ~/.ssh/robot_$(hostname) -C "admin@$(hostname)"
ssh-copy-id -i ~/.ssh/robot_$(hostname).pub -p 2222 robot-admin@10.10.30.5
fail2ban for Robot Computers
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
sudo apt install fail2ban -y && sudo systemctl enable --now fail2ban
Unattended Security Updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
# Key settings in /etc/apt/apt.conf.d/50unattended-upgrades:
# Allowed-Origins: "${distro_id}:${distro_codename}-security"
# Automatic-Reboot: "false" # NEVER auto-reboot a running robot
Minimal Installed Packages
# Remove unnecessary packages from robot computers
sudo apt purge -y avahi-daemon cups snapd modemmanager bluetooth bluez
sudo apt autoremove -y
Secrets Management
No Hardcoded Credentials
# BAD:
class FleetClient:
def __init__(self):
self.api_key = "sk-live-abc123xyz789"
# GOOD:
import os
class FleetClient:
def __init__(self):
self.api_key = os.environ['FLEET_API_KEY']
# BAD: credentials in params.yaml tracked by git
fleet_manager:
ros__parameters:
aws_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
# GOOD: reference environment variables
fleet_manager:
ros__parameters:
aws_secret_key: "$(env AWS_SECRET_KEY)"
Environment-Based Secrets for ROS2 Nodes
# /etc/systemd/system/robot-nav.service
[Service]
User=robot
Group=robot
EnvironmentFile=/etc/robot/secrets.env
ExecStart=/opt/ros/humble/bin/ros2 launch my_robot nav.launch.py
Restart=always
# /etc/robot/secrets.env
FLEET_API_KEY=sk-live-actual-key-here
ROS_SECURITY_KEYSTORE=/opt/robot/sros2_keystore
# Lock it down
sudo chown root:robot /etc/robot/secrets.env
sudo chmod 640 /etc/robot/secrets.env
Certificate Rotation Patterns
#!/bin/bash
# rotate_certs.sh — run via cron monthly
set -euo pipefail
KEYSTORE="/opt/robot/sros2_keystore"
cp -r "${KEYSTORE}" "${KEYSTORE}_backup_$(date +%Y%m%d)"
for enclave in motor_controller navigation camera_driver teleop; do
ros2 security create_enclave "${KEYSTORE}" "/my_robot/${enclave}"
done
sudo systemctl restart robot-*.service
echo "Certificates rotated at $(date)"
# /etc/cron.d/robot-cert-rotation
0 3 1 * * root /opt/robot/scripts/rotate_certs.sh >> /var/log/cert-rotation.log 2>&1
File Permissions for Keystores
sudo chown -R root:robot /opt/robot/sros2_keystore
sudo find /opt/robot/sros2_keystore -type d -exec chmod 750 {} \;
sudo find /opt/robot/sros2_keystore -type f -exec chmod 640 {} \;
# CA private key — root only
sudo chmod 600 /opt/robot/sros2_keystore/private/ca.key.pem
sudo chown root:root /opt/robot/sros2_keystore/private/ca.key.pem
Container Security
Non-Root Containers
FROM ros:humble-ros-base AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
ros-humble-nav2-bringup && rm -rf /var/lib/apt/lists/*
RUN groupadd -g 1000 robot && useradd -u 1000 -g robot -m -s /bin/false robot
COPY --from=builder /opt/ros2_ws/install /opt/ros2_ws/install
USER robot:robot
ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["ros2", "launch", "my_robot", "nav.launch.py"]
Minimal Runtime Images
FROM ros:humble-desktop AS builder
WORKDIR /opt/ros2_ws
COPY src/ src/
RUN . /opt/ros/humble/setup.sh && \
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --merge-install
FROM ros:humble-ros-core AS runtime
COPY --from=builder /opt/ros2_ws/install /opt/ros2_ws/install
# Remove shell and package manager — prevents interactive exploitation
RUN rm -f /bin/sh /bin/bash /bin/dash && apt-get purge -y --auto-remove apt
Image Scanning and Signing
trivy image --severity HIGH,CRITICAL my-robot/navigation:latest
cosign sign --key cosign.key my-registry.io/my-robot/navigation:v1.2.3
cosign verify --key cosign.pub my-registry.io/my-robot/navigation:v1.2.3 || exit 1
Read-Only Root Filesystem
# docker-compose.yml
services:
motor_controller:
image: my-robot/motor-controller:v1.0.0
user: "1000:1000"
read_only: true
tmpfs: ["/tmp:size=64M", "/var/log/ros:size=32M"]
volumes:
- type: bind
source: /opt/robot/sros2_keystore/enclaves/my_robot/motor_controller
target: /keystore
read_only: true
security_opt: ["no-new-privileges:true"]
cap_drop: [ALL]
environment:
ROS_SECURITY_KEYSTORE: /keystore
ROS_SECURITY_ENABLE: "true"
ROS_SECURITY_STRATEGY: Enforce
Physical-Cyber Safety Intersection
Cyber attacks on robots cause physical harm. Standard IT security is necessary but not sufficient.
E-Stop Independence
The emergency stop must function with all software, network, and main compute completely dead.
┌──────────┐ HARDWIRED ┌─────────────────┐
│ Physical │ ─────────────────▶│ Safety Relay / │──▶ Motor power cut
│ E-Stop │ Direct circuit │ Safety PLC │ via contactor
│ Button │ NO software └─────────────────┘
└──────────┘
┌──────────┐ OPTIONAL
│ Software │ ───(notifies)───▶ Can trigger relay, but NOT sole path
│ E-Stop │
└──────────┘
Main compute crash ──X──▶ Cannot prevent hardware e-stop
Network failure ──X──▶ Cannot prevent hardware e-stop
Design rules: hardwired circuit disconnects motor power; software triggers the relay but is never the only path; wireless e-stops use dedicated radio, not WiFi.
Safety Controller Isolation
┌──────────────────────────────┬───────────────────────────────┐
│ MAIN COMPUTE (Jetson/x86) │ SAFETY CONTROLLER (STM32/MCU) │
│ Ubuntu + ROS2 │ Bare-metal firmware │
│ Nav, Perception, Planning │ │
│ ──── CAN/UART ──▶│ Validates: │
│ cmd_vel │ - Max velocity │
│ │ - Max acceleration │
│ ◀── joint_fb ────│ - Workspace limits │
│ │ - Watchdog timeout │
│ If compromised, safety │ Rejects out-of-bounds cmds │
│ controller STILL enforces │ Runs on separate hardware │
│ physical limits. │ Does NOT run ROS2 or Linux │
└──────────────────────────────┴───────────────────────────────┘
Command Velocity Validation and Rate Limiting
Enforce at the driver level — last line of defense before actuators:
# velocity_safety_gate.py
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
class VelocitySafetyGate(Node):
def __init__(self):
super().__init__('velocity_safety_gate')
self.declare_parameter('max_linear_vel', 1.0) # m/s
self.declare_parameter('max_angular_vel', 2.0) # rad/s
self.declare_parameter('max_linear_accel', 0.5) # m/s^2
self.declare_parameter('cmd_timeout_sec', 0.5)
self.declare_parameter('max_cmd_rate_hz', 50.0)
self.max_lin = s
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [arpitg1304](https://github.com/arpitg1304)
- **Source:** [arpitg1304/robotics-agent-skills](https://github.com/arpitg1304/robotics-agent-skills)
- **License:** Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.