Back to skill

Security audit

Reachy Mini

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Reachy Mini robot-control tool, but it grants broad physical, camera, microphone, app, API, and SSH authority with weak scoping and insecure SSH defaults that users should review before installing.

Install only if you intend to let the agent control a specific Reachy Mini and you can supervise physical motion, camera capture, and microphone-based reactions. Before use, change any factory/default SSH credentials, prefer pinned SSH keys and host-key verification, avoid unattended heartbeat patrol/DOA behavior unless everyone nearby consents, and restrict raw/app/system operations to explicit user-approved tasks.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/reachy.sh:376
Finding

Unverified Predictable Remote Temporary Script Can Be Hijacked

Content
View full analysis
/dev/null || { echo "Deploying snapshot script..." >&2 scp_to "${SCRIPT_DIR}/reachy-gst-snap.py" "${REMOTE_SCRIPT}" 2>/dev/null \ || die "Failed to deploy snapshot script via SCP" } # Run capture on the robot ssh_cmd " export GST_PLUGIN_PATH=/opt/gst-plugins-rs/lib/aarch64-linux-gnu/gstreamer-1.0 # Get producer ID from WebRTC signalling server PRODUCER=\$(/venvs/apps_venv/bin/python3 -c \" import asyncio, json, websockets async def p(): async with websockets.connect('ws://127.0.0.1:8443') as ws: await ws.recv() await ws.send(json.dumps({'type': 'setPeerStatus', 'roles': ['listener'], 'meta': {}})) await ws.recv() await ws.send(json.dumps({'type': 'list'})) listing = json.loads(await ws.recv()) if listing.get('producers'): print(listing['producers'][0]['id']) asyncio.run(p()) \" 2>/dev/null) if [ -z \"\$PRODUCER\" ]; then echo 'ERROR: No WebRTC producer found. Is the daemon running?' >&2 exit 1 fi rm -f ${REMOTE_SNAP} timeout 20 /venvs/apps_venv/bin/python3 ${REMOTE_SCRIPT} ${REMOTE_SNAP} \"\$PRODUCER\" 2>&1 \ | grep -v 'BUS ERROR\|Signalling error\|receiver is gone' " || die "Capture failed on robot" ``` ### Technical Analysis The snapshot workflow uses the fixed remote path `/tmp/reachy_gst_snap.py`. Before execution, it checks only whether a file exists at that path. It does not verify the file's cryptographic hash, owner, permissions, type, or contents. Although the comment states that the ...[truncated 1927 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/reachy.sh:136
Finding

Default SSH Password and Disabled Host-Key Verification Enable Credential Exposure and Endpoint Impersonation

Content
View full analysis
/dev/null && [[ -n "$REACHY_SSH_PASS" ]]; then sshpass -p "$REACHY_SSH_PASS" ssh -F /dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${REACHY_SSH_USER}@${REACHY_HOST}" "$@" else ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${REACHY_SSH_USER}@${REACHY_HOST}" "$@" fi } scp_from() { local remote="$1" local="$2" if command -v sshpass &>/dev/null && [[ -n "$REACHY_SSH_PASS" ]]; then sshpass -p "$REACHY_SSH_PASS" scp -F /dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${REACHY_SSH_USER}@${REACHY_HOST}:${remote}" "${local}" else scp -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${REACHY_SSH_USER}@${REACHY_HOST}:${remote}" "${local}" fi } scp_to() { local localfile="$1" remote="$2" if command -v sshpass &>/dev/null && [[ -n "$REACHY_SSH_PASS" ]]; then sshpass -p "$REACHY_SSH_PASS" scp -F /dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${localfile}" "${REACHY_SSH_USER}@${REACHY_HOST}:${remote}" else scp -o StrictHostKeyChecking=no -o ConnectTimeout=5 \ "${localfile}" "${REACHY_SSH_USER}@${REACHY_HOST}:${remote}" fi } ``` ### Technical Analysis The Skill assigns `root` as the default SSH password and automatically uses it through `sshpass` when available. A shared default password is not a secure secret and permits unauthorized access wherever the robot retains that credential. All SSH and SCP operations also specify `StrictHostKeyChecking=no`. The password-authenticated branch additionally uses `-F /dev/null`, discarding normal SSH client configuration. Consequently, the client does not ...[truncated 2553 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (13)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The patrol behavior explicitly supports periodic room snapshots and integration with heartbeats, but it does not present a clear privacy warning, consent requirement, retention guideline, or notification expectation. In a real environment, scheduled image capture of a room can collect bystanders, sensitive screens, or private surroundings without informed consent.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/reachy-react.sh (reported line 32)May include surrounding context.

sh
# Quick connectivity check (200ms timeout)
is_reachable() {
  curl -sf --max-time 1 "http://${REACHY_HOST}:8000/" >/dev/null 2>&1
}

# Get robot state (not_initialized, starting, running, etc.)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill exposes shell-based robot control, SSH access, app management, camera capture, and raw API calls, but it does not declare any explicit tool scope or allowed-tools boundary. In an agent environment, this increases the chance that the skill is invoked with unrestricted shell capability, enabling unintended physical actions, camera access, or service manipulation on the robot.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation text is broad enough to trigger on nearly any robot-related or physical-interaction request, which can cause the agent to invoke a high-impact skill in situations where safer clarification or human confirmation is needed. Because this skill can move hardware, capture images, and manage apps, overbroad matching raises the risk of unintended physical actions and privacy-sensitive operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The DOA tracking feature uses the microphone array to detect speech direction and trigger motion, but the skill omits an explicit warning that microphone-based sensing is occurring. Even if it only uses direction and speech detection rather than full transcription, it still performs environmental audio sensing that may surprise users and create privacy concerns.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 233)May include surrounding context.

Via curl directly

curl -s http://192.168.8.17:8000/api/state/full | jq curl -s -X POST -H "Content-Type: application/json"
-d '{"duration":1.5,"head_pose":{"pitch":0,"yaw":0.3,"roll":0}}'
http://192.168.8.17:8000/api/move/goto

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This reference exposes operations that can change connectivity, install/start apps, restart services, and trigger firmware updates on a physical robot without any cautionary guidance, confirmation requirements, or mention of operational risk. In the context of an agent skill for robot control, that omission increases the chance an LLM-driven agent will perform disruptive or unsafe actions on behalf of a user without adequate safeguards.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/reachy-react.sh (reported line 284)May include surrounding context.

sh
if $BG; then
  run_reaction "$@" &
  disown
  echo "Reaction '$REACTION' running in background"
else
  run_reaction "$@"

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documented raw METHOD PATH [BODY] interface exposes unrestricted access to arbitrary API endpoints on the robot daemon. That bypasses the safety boundaries implied by the curated commands and allows an agent or caller to invoke undocumented or dangerous functions, potentially including state changes, app management, or maintenance operations not otherwise intended.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/reachy.sh (reported line 118)May include surrounding context.

sh
local url="${BASE}${path}"
  [[ -n "$query" ]] && url="${url}?${query}"
  if [[ -n "$body" ]]; then
    curl -sf --max-time 15 -X POST -H "Content-Type: application/json" -d "$body" "$url" 2>/dev/null \
      || die "Request failed: POST $path"
  else
    curl -sf --max-time 15 -X POST "$url" 2>/dev/null \

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script defines reusable SSH and SCP helpers that allow remote command execution and file transfer to the robot host, not just narrowly scoped robot-control API calls. In a skill exposed to an agent, this broadens capability significantly: if the host or target paths are influenced by prompts or future code changes, the skill can be used to execute arbitrary commands on the robot and move files without additional safeguards.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill reads an SSH password from environment and defaults it to root, then uses sshpass for non-interactive login. A built-in default credential for remote access is highly dangerous because it normalizes insecure authentication and can enable unauthorized access to the robot if the same credential is valid on the target.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The snap command writes captured image data to a local path supplied by the user or to /tmp/reachy_snap.jpg by default, and it also removes temporary remote files. While the help text documents the output path, it does not explicitly warn that invoking this command creates or overwrites a local file and performs remote temporary file cleanup.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.