Back to skill

Security audit

ros2-engineering-skills

Security checks for vulnerabilities and agentic risk

Overview

This ROS 2 skill is mostly a coherent engineering guide, but it includes unsafe privileged setup guidance and an input-validation flaw in its package generator.

Review this skill before installing in an agent that may execute suggested commands. Avoid the pipe-to-shell Tailscale command, scrutinize privileged Docker and system-tuning examples before running them, and do not pass untrusted maintainer metadata to scripts/create_package.py unless validation is added.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
references/security.md:497
Finding
Mutable Remote Installer Executed Directly Through a Shell<![CDATA[ ## Vulnerability Details **File Location**: `references/security.md:497-500` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```bash # Tailscale: install on each robot, assigns 100.x.y.z addresses curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up --hostname=robot-001 # Use Tailscale IPs in CycloneDDS peer list ``` ### Technical Analysis The documentation pipes the response from a mutable external URL directly into `sh`. The downloaded content is not pinned to a version, saved for inspection, checked against an expected digest, or authenticated through a package-signing workflow. Although HTTPS protects the connection under normal conditions and the URL appears to be associated with the named vendor, the effective code executed by this instruction can change after the Skill has been reviewed. Compromise of the vendor domain, hosting infrastructure, TLS trust chain, or installer publication process would turn this command into an arbitrary code-execution channel. The installation operation is system-wide and is followed by a privileged `sudo tailscale up` command. Vendor installation scripts commonly require or invoke elevated operations to configure package repositories, install software, and register services. Consequently, this instruction can cross the least-privilege boundary of a documentation-only ROS 2 networking task. ### Attack Path 1. An attacker compromises the remote installer, its hosting infrastructure, or another trusted component in the delivery chain. 2. The attacker replaces or modifies the response served from `https://tailscale.com/install.sh`. 3. A user or AI agent follows the Skill's documented installation command on a robot. 4. `curl` streams the attacker-controlled response directly to `sh`, without an opportunity for local review. 5. The payload executes on the robot and may invoke privileged installation operations. 6. The payload can modify s ...[truncated 1037 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `curl | sh` pipeline. 2. Prefer the vendor's signed operating-system repository and package-manager installation procedure. 3. Pin an explicit repository, package version, or release rather than retrieving a mutable installer. 4. Verify the repository signing-key fingerprint through an independently authenticated source. 5. Require package signature verification before installation. 6. If a standalone installer is unavoidable: - Download it to a local file. - Pin an expected SHA-256 or stronger digest. - Verify the digest and any detached signature. - Inspect the script before execution. - Run it with the minimum privileges required. 7. Separate installation from activation so users can review the changes before running `sudo tailscale up`. 8. Document expected filesystem, service, firewall, and network changes. 9. For fleet deployment, distribute verified artifacts from an organization-controlled repository rather than downloading mutable scripts independently on every robot. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_package.py:20
Finding
Unescaped Maintainer Metadata Can Inject Code into Generated Packages<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_package.py:20-58` **Additional Relevant Locations**: `scripts/create_package.py:1274`, `scripts/create_package.py:1304-1307`, `scripts/create_package.py:1332-1342` **Vulnerability Type**: Generated source-code and XML injection **Risk Level**: Medium ### Vulnerable Code The maintainer value is inserted directly into generated Python and C++ comment headers: ```python _APACHE2_PY = """# Copyright 2024 {maintainer} # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ _APACHE2_CPP = """// Copyright 2024 {maintainer} // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. """ def _copyright_py(maintainer: str = "TODO") -> str: return _APACHE2_PY.format(maintainer=maintainer) def _copyright_cpp(maintainer: str = "TODO") -> str: return _APACHE2_CPP.format(maintainer=maintainer) ``` The same unescaped values are embedded in XML: ```python <maintainer email="{maintainer_email}">{maintainer_name}</maint ...[truncated 3716 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject carriage returns, line feeds, NUL bytes, and other control characters in both maintainer fields. 2. Apply a conservative allowlist to maintainer names, or explicitly support Unicode names while prohibiting characters that can change source-code structure. 3. Validate the email address with a dedicated parser and reject newlines, quotes, angle brackets, and control characters. 4. Generate `package.xml` with an XML library such as `xml.etree.ElementTree`, allowing the library to escape element text and attribute values. 5. Do not interpolate untrusted text directly into source-code templates. 6. If multiline attribution is required, split it into lines and prepend the appropriate comment marker to every line: - `# ` for Python. - `// ` for C++. 7. Add regression tests covering: - Newline-based Python injection. - Newline-based C++ injection. - XML attribute breakout. - XML element injection. - Ampersands and quotation marks. 8. Generate files into a temporary directory, validate that Python files parse and XML files are well-formed, and only then move them into the destination. 9. Clearly document that metadata imported from repositories or manifests must be treated as untrusted input. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (139)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description represents a general-purpose ROS 2 expert/guide skill, but the supplied code implements a specific launch-file validator. Its primary purpose is materially different: static checking of Python ROS 2 launch files, not comprehensive ROS 2 engineering assistance. The code does not provide guidance or functionality for most of the listed domains and even explicitly limits itself to .launch.py files, excluding XML and YAML launch files. This is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description presents this skill as a wide-ranging ROS 2 engineering guide covering nearly the full ROS 2 ecosystem. The supplied code chunk, however, is only a test suite for a package creation script. It verifies that the script scaffolds ROS 2 C++/Python/interfaces packages with expected files and metadata, and checks CLI validation behaviors. That is a legitimate ROS 2-related utility, but it is materially narrower than the declared purpose. The mismatch is primarily one of scope and primary purpose: the code does not provide comprehensive ROS 2 engineering guidance or functionality across the many listed domains; it only supports package scaffolding. The broad trigger conditions are therefore also inaccurate relative to actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
There is a clear description-behavior mismatch. The declared purpose presents the skill as an expansive ROS 2 engineering guide covering nearly all major ROS 2 subsystems and workflows. In contrast, the supplied code is narrowly focused on testing a single utility for static analysis of ROS 2 launch files. While this falls within the broad ROS 2 ecosystem, it does not substantiate the claimed comprehensive functionality. The code neither implements guidance across the listed domains nor demonstrates capabilities beyond launch validation. This is not merely an incomplete snippet of a large guide; the observable behavior is specifically a validator test suite with CLI and AST/rule checks, making the declared purpose materially broader and different from the actual code behavior.

Ae1

High
Category
analysis-evasion
Content
| ROS 1 migration, ros1_bridge, hybrid operation | `references/migration-ros1.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| ROS 1 migration, ros1_bridge, hybrid operation | `references/migration-ros1.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
reduces CPU
overhead and network bandwidth for subscribers that only need a subset of messages.

### Basic API

```cpp
auto options = rclcpp::SubscriptionOptions();
// SQL-like filter expression with positional parameters
// Filter on top-level fields of the message type only
options.content_filter_options.filter_expression = "temperature > %0";
options.content_filter_options.expression_parameters = {"80.0"};

auto sub = create_subscription<sensor_msgs::msg::Temperature>(
  "diagnostics/temperature", rclcpp::SensorDataQoS(),
  [this](const sensor_msgs::msg::Temperature::SharedPtr msg) {
    // Only called when temperature > 80.0 — filtering happens at DDS layer
    RCLCPP_WARN(get_logger(), "High engine temperature: %.1f", msg->temperature);
  },
  options);
```

**Limitation:** Content filters operate on top-level message fields only. You cannot
filter on nested fields (e.g., `status[].level` inside `DiagnosticArray`). For nested
filtering, subscribe normally
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Hidden Instructions

High
Category
Prompt Injection
Content
### CycloneDDS tuning (default vendor)

```xml
<!-- cyclonedds.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<CycloneDDS xmlns="https://cdds.io/config">
  <Domain>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# Enable core dumps
ulimit -c unlimited
echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern

# After crash, analyze with GDB
gdb /path/to/driver_node /tmp/core.driver_node.12345
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# Enable core dumps
ulimit -c unlimited
echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern

# After crash, analyze with GDB
gdb /path/to/driver_node /tmp/core.driver_node.12345
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# Enable core dumps
ulimit -c unlimited
echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern

# After crash, analyze with GDB
gdb /path/to/driver_node /tmp/core.driver_node.12345
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# Enable core dumps
ulimit -c unlimited
echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern

# After crash, analyze with GDB
gdb /path/to/driver_node /tmp/core.driver_node.12345
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
rosdep update && \
    rosdep install --from-paths /tmp/src --ignore-src -y \
    --skip-keys "ament_cmake ament_lint_auto" && \
    rm -rf /tmp/src /var/lib/apt/lists/*

# Entry point
COPY docker/entrypoint.sh /entrypoint.sh
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
rosdep update && \
    rosdep install --from-paths /tmp/src --ignore-src -y \
    --skip-keys "ament_cmake ament_lint_auto" && \
    rm -rf /tmp/src /var/lib/apt/lists/*

# Entry point
COPY docker/entrypoint.sh /entrypoint.sh
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
rosdep update && \
    rosdep install --from-paths /tmp/src --ignore-src -y \
    --skip-keys "ament_cmake ament_lint_auto" && \
    rm -rf /tmp/src /var/lib/apt/lists/*

# Entry point
COPY docker/entrypoint.sh /entrypoint.sh
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Privileged Container / Container Escape

High
Category
Privilege Escalation
Content
For shared memory transport inside Docker:
```bash
# Required for iceoryx/CycloneDDS shared memory
docker run --ipc=host ...
```

## 2. Cross-compilation (aarch64, armhf)
Confidence
88% confidence
Finding
Using `--ipc=host` shares the host IPC namespace with the container, reducing isolation and potentially exposing shared-memory segments or enabling interference between host and container processes. In robotics deployments, this may be justified for performance, but it still increases blast radius if the container is compromised.

Privileged Container / Container Escape

High
Category
Privilege Escalation
Content
```bash
# Enable multi-arch builds
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

# Build for ARM64
docker buildx build \
Confidence
93% confidence
Finding
Running a container with `--privileged` gives it broad access to host devices, kernel capabilities, and security-sensitive interfaces, substantially weakening container isolation. If the image or executed code is compromised, an attacker could pivot to the host and potentially take over the build machine.

Hidden Instructions

High
Category
Prompt Injection
Content
<param name="min">-3.14</param>
    <param name="max">3.14</param>
  </command_interface>
  <!-- Hardware-layer limits (enforced by framework, not controller) -->
  <limit effort="100.0" velocity="2.0" lower="-3.14" upper="3.14"/>
</joint>
```
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
"joint_6" value="0"/>
  </group_state>

  <!-- End effector definition -->
  <end_effector name="gripper" parent_link="tool0"
                group="gripper" parent_group="arm"/>

  <!-- Disable collision checking between adjacent links -->
  <disable_collisions link1="base_link" link2="link_1" reason="Adjacent"/>
  <disable_collisions link1="link_1" link2="link_2" reason="Adjacent"/>
  <!-- ... generated by MoveIt Setup Assistant -->
</robot>
```

### Kinematics configuration

```yaml
# kinematics.yaml
arm:
  kinematics_solver: kdl_kinematics_plugin/KDLKinematicsPlugin
  kinematics_solver_search_resolution: 0.005
  kinematics_solver_timeout: 0.05   # seconds
  # For 6+ DOF arms, consider:
  # kinematics_solver: pick_ik/PickIkPlugin   # Faster for complex IK
```

### Joint limits override

```yaml
# joint_limits.yaml — override URDF limits for MoveIt
joint_limits:
  joint_1:
    has_velocity_limits: true
    max_velocity: 2.0             # rad/s
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
erfaces` package with `rosidl_generate_interfaces`

### Custom bridge mapping for mismatched types

```yaml
# mapping_rules.yaml — for types with different names/structures
-
  ros1_package_name: 'my_robot_msgs'
  ros1_message_name: 'RobotStatus'
  ros2_package_name: 'my_robot_interfaces'
  ros2_message_name: 'RobotStatus'
  fields_1_to_2:
    header: 'header'
    mode: 'mode'
    description: 'description'
    battery_voltage: 'battery_voltage'
```

## 4. Launch file conversion

### ROS 1 XML → ROS 2 Python

**ROS 1 (XML):**
```xml
<launch>
  <arg name="robot_name" default="my_robot"/>
  <arg name="use_sim" default="false"/>

  <param name="robot_description"
         command="$(find xacro)/xacro $(find my_robot_description)/urdf/robot.urdf.xacro"/>

  <node pkg="robot_state_publisher" type="robot_state_publisher"
        name="robot_state_publisher" output="screen"/>

  <node pkg="my_robot_driver" type="driver_node" name="driver"
        ns="$(a
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Chaining Abuse

High
Category
Tool Misuse
Content
# x86/amd64 (GRUB bootloader):
# /etc/default/grub — isolate CPUs 2 and 3 for RT
GRUB_CMDLINE_LINUX="isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3"
sudo update-grub && sudo reboot

# NVIDIA Jetson (U-Boot/extlinux):
# Edit /boot/extlinux/extlinux.conf, add to APPEND line:
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Hidden Instructions

High
Category
Prompt Injection
Content
<liveliness_protection_kind>ENCRYPT</liveliness_protection_kind>
      <rtps_protection_kind>ENCRYPT</rtps_protection_kind>
      <topic_access_rules>
        <!-- High-bandwidth sensors: sign only (integrity without encryption overhead) -->
        <topic_rule>
          <topic_expression>rt/camera/*</topic_expression>
          <enable_discovery_protection>true</enable_discovery_protection>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Credential Access

High
Category
Privilege Escalation
Content
# CORRECT — use only the official OSRF repositories
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
  -o /usr/share/keyrings/ros-archive-keyring.gpg
```

---
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Hidden Instructions

High
Category
Prompt Injection
Content
DDS multicast discovery is not forwarded over VPN tunnels. Use unicast peer lists:

```xml
<!-- cyclonedds_vpn.xml — unicast discovery for VPN -->
<CycloneDDS>
  <Domain>
    <General>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

External Script Fetching

High
Category
Supply Chain
Content
```bash
# Tailscale: install on each robot, assigns 100.x.y.z addresses
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --hostname=robot-001
# Use Tailscale IPs in CycloneDDS peer list
Confidence
98% confidence
Finding
Piping a remotely fetched script directly into sh executes unverified code from the network with no integrity check or review step. In a robotics/security guide, this is especially dangerous because a compromised install endpoint, MITM, or supply-chain incident could lead to arbitrary code execution on robots or operator systems.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# Tailscale: install on each robot, assigns 100.x.y.z addresses
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --hostname=robot-001
# Use Tailscale IPs in CycloneDDS peer list
Confidence
99% confidence
Finding
The use of curl ... | sh combines untrusted network retrieval with immediate shell execution, which is a classic unsafe chaining pattern. Given this skill is about securing ROS 2 systems, including such a pattern weakens the trustworthiness of the guidance and creates a realistic path to arbitrary code execution during deployment.

Static analysis

Detected: suspicious.generated_source_template_injection

User-controlled placeholder is embedded directly into generated source code.

Critical
Code
suspicious.generated_source_template_injection
Location
references/deployment.md:319