Back to skill

Security audit

Pi Admin

Security checks for vulnerabilities and agentic risk

Overview

This Raspberry Pi admin skill is mostly purpose-aligned, but it can reboot the host, kill and restart services, and persistently change system settings with several misleading or under-scoped safety controls.

Install only on a Raspberry Pi you administer and treat it as a privileged maintenance tool, not just a monitor. Review and preferably fix the confirmation behavior, dry-run side effects, hardcoded gateway path and addresses, port mismatch, and optimization undo logic before allowing agents or automation to invoke maintenance commands.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Warning
Location
update.sh:32
Finding
Update Dry-Run Performs Privileged Network and Filesystem Mutations## Vulnerability Details **File Location**: `update.sh:32-63` **Vulnerability Type**: Dry-run safety contract violation **Risk Level**: Medium ### Vulnerable Code ```bash else # In dry-run mode, we need sudo for read operations SUDO="sudo" fi # Update package lists echo "Updating package lists..." $SUDO apt update # Show upgradable packages echo "" echo "Upgradable packages:" echo "--------------------" $SUDO apt list --upgradable 2>/dev/null | grep -v "^Listing" | head -20 # Count packages COUNT=$($SUDO apt list --upgradable 2>/dev/null | grep -v "^Listing" | wc -l) if [ "$COUNT" -eq 0 ]; then echo "" echo "✅ System is up to date!" exit 0 fi echo "" echo "Found $COUNT upgradable package(s)" echo "" # Exit early in dry run mode if [ "$DRY_RUN" = true ]; then echo "🔍 Dry run complete. These packages would be updated." echo " Run without --dry-run to apply updates." exit 0 fi ``` ### Technical Analysis The script advertises dry-run mode as making no changes, but assigns `SUDO="sudo"` in that mode and executes `sudo apt update` before reaching the dry-run exit. `apt update` is not a read-only operation: it contacts configured package repositories and modifies package-index state under `/var/lib/apt/lists` and related APT-managed paths. This violates the documented dry-run safety contract and unnecessarily requests elevated privileges for a preview operation. It can also trigger repository authentication, proxy access, metered network traffic, or interaction with an untrusted repository configured on the host. ### Attack Path 1. A user or automation system invokes `./skill.sh update --dry-run`, expecting a side-effect-free preview. 2. The wrapper forwards `--dry-run` to `update.sh`. 3. The script assigns `sudo` to `SUDO`. 4. `sudo apt update` contacts every configured APT repository. 5. APT downloads metadata and changes privileged local package-inde ...[truncated 506 chars]
Remediation
## Remediation Suggestions - Do not run `apt update` in dry-run mode. - Use existing package indexes for the preview, or introduce a separately named and explicitly confirmed `--refresh` option. - Do not assign `sudo` for operations that only read publicly accessible APT state. - Clearly distinguish between a side-effect-free preview and a repository refresh. - Enable fail-safe shell behavior such as `set -euo pipefail` and check command exit statuses before reporting success. - Add a regression test that records relevant filesystem state and network calls to verify that `--dry-run` performs no writes or downloads.

T09 · Insecure Skill Coding Practices

Warning
Location
optimize.sh:100
Finding
Optimization Undo Overwrites Persistent System State Without Restoring the Original Configuration## Vulnerability Details **File Location**: `optimize.sh:100-125` **Vulnerability Type**: Unsafe persistent service and kernel configuration restoration **Risk Level**: Medium ### Vulnerable Code ```bash # Undo mode if [ "$UNDO" = true ]; then echo "Reverting optimizations..." echo "" if [ "$(systemctl is-enabled bluetooth.service)" = "disabled" ]; then echo "Enabling Bluetooth..." $SUDO systemctl enable bluetooth.service echo "✅ Bluetooth enabled" fi if [ "$(systemctl is-enabled ModemManager.service)" = "disabled" ]; then echo "Enabling ModemManager..." $SUDO systemctl enable ModemManager.service echo "✅ ModemManager enabled" fi if [ "$(systemctl is-enabled avahi-daemon.service)" = "disabled" ]; then echo "Enabling Avahi..." $SUDO systemctl enable avahi-daemon.service echo "✅ Avahi enabled" fi echo "Restoring swappiness to 60..." $SUDO sysctl vm.swappiness=60 echo "vm.swappiness=60" | $SUDO tee /etc/sysctl.d/99-swappiness.conf > /dev/null echo "✅ Swappiness restored to 60" ``` Related persistent optimization operations occur at `optimize.sh:137-173`: ```bash $SUDO systemctl disable bluetooth.service $SUDO systemctl disable ModemManager.service $SUDO systemctl disable avahi-daemon.service $SUDO sysctl vm.swappiness=10 echo "vm.swappiness=10" | $SUDO tee /etc/sysctl.d/99-swappiness.conf > /dev/null ``` ### Technical Analysis The optimization feature legitimately requires persistent configuration changes because its declared purpose includes disabling services and setting swappiness across reboots. These operations are therefore not evidence of a covert backdoor. However, the implementation does not record the original service enablement states or original swappiness configuration. Consequently, `--undo` does not actually restore prior state. It enables every target service that is currently disabled, even if ...[truncated 1543 chars]
Remediation
## Remediation Suggestions - Before applying optimizations, record each service’s exact original state, including `enabled`, `disabled`, `masked`, `static`, and absent states. - Record the effective swappiness value and whether the Skill-created sysctl file existed beforehand. - Store restoration data in a root-owned file with restrictive permissions and validate its format before use. - During undo, restore only settings that a recorded optimization run actually changed. - Remove the Skill-created sysctl file when appropriate instead of replacing unknown prior policy with a hardcoded value. - Never unmask or enable a service that was already disabled or masked before optimization. - Display the exact persistent changes and require affirmative confirmation before both apply and undo operations. - Check every `systemctl`, `sysctl`, and `tee` exit status before claiming success.

T09 · Insecure Skill Coding Practices

Warning
Location
restart-gateway.sh:27
Finding
Destructive Reboot and Gateway Termination Operations Lack Affirmative Confirmation## Vulnerability Details **File Locations**: `restart-gateway.sh:27-49`; `reboot.sh:27-41`; documentation at `SKILL.md:154` **Vulnerability Type**: Unsafe destructive process and availability management **Risk Level**: Medium ### Vulnerable Code `restart-gateway.sh:27-49`: ```bash # Stop running gateway processes echo "Stopping any running gateway processes..." pkill -f "clawdis gateway" 2>/dev/null sleep 2 # Check if processes are still running REMAINING=$(pgrep -f "clawdis gateway" | wc -l) if [ "$REMAINING" -gt 0 ]; then echo "Force stopping remaining processes..." pkill -9 -f "clawdis gateway" 2>/dev/null sleep 1 fi echo "✅ Gateway processes stopped" echo "" # Start new gateway echo "Starting Gateway on port 18789..." cd /home/srose/clawdis # Start in background pnpm clawdis gateway --port 18789 > /dev/null 2>&1 & ``` `reboot.sh:27-41`: ```bash echo "⚠️ This will reboot the system!" echo "" echo "To cancel, press Ctrl+C" echo "" # Countdown for i in {10..1}; do echo -ne "\rRebooting in $i seconds... " sleep 1 done echo "" echo "" echo "🔄 Rebooting now..." $SUDO reboot ``` The documentation states: ```text All maintenance commands require sudo and ask for confirmation before making changes. ``` ### Technical Analysis Neither operation obtains affirmative user consent. The reboot command merely provides a countdown, while the gateway restart immediately sends termination signals. The gateway script uses `pkill -f "clawdis gateway"`, which matches the full command line rather than a verified process identity. This can terminate unrelated processes whose arguments happen to contain the same string. It escalates to `SIGKILL`, preventing matched processes from performing graceful shutdown or cleanup. The script then changes into a hardcoded directory without checking whether `cd` succeeded. Because shell execution continues a ...[truncated 1221 chars]
Remediation
## Remediation Suggestions - Require an explicit yes/no confirmation before terminating processes or rebooting. - Provide a separately documented `--yes` option for controlled, noninteractive automation. - Manage the gateway through a dedicated systemd unit or another process supervisor. - If a service manager is unavailable, use a protected PID file and verify the PID’s executable, owner, and start time before signaling it. - Avoid `pkill -f`; never use broad `SIGKILL` matching as the default shutdown mechanism. - Attempt graceful termination, wait for the exact process, and use `SIGKILL` only for that verified PID after a defined timeout. - Change directories using `cd /home/srose/clawdis || exit 1`. - Replace hardcoded user-specific paths and addresses with validated configuration. - Check restart and reboot command results before reporting success. - Correct the documentation so its confirmation guarantees match actual behavior.

other

Note
Location
network.sh:9
Finding
Combined Inventory Commands Expose Broad Host and Network Reconnaissance Data## Vulnerability Details **File Locations**: `network.sh:9-48`, `tailscale.sh:17-48`, `services.sh:21-45`, `storage.sh:33-41`, dispatched collectively by `skill.sh:50-70` **Vulnerability Type**: Excessive system reconnaissance and information exposure **Risk Level**: Low ### Representative Code `network.sh:9-48`: ```bash echo "Hostname: $(hostname)" echo "FQDN: $(hostname -f 2>/dev/null || echo "N/A")" hostname -I 2>/dev/null | tr ' ' '\n' | while read ip; do [ -n "$ip" ] && echo " - $ip" done for iface in /sys/class/net/*; do name=$(basename "$iface") if [ -f "$iface/operstate" ]; then state=$(cat "$iface/operstate") mac=$(cat "$iface/address" 2>/dev/null) ip=$(ip -4 addr show "$name" 2>/dev/null | grep -oP 'inet \K[0-9.]+' | head -1) echo " $name: $state" [ -n "$ip" ] && echo " IP: $ip" [ -n "$mac" ] && echo " MAC: $mac" fi done cat /etc/resolv.conf 2>/dev/null | grep nameserver | while read line; do echo " $line" done ip route | grep default | awk '{print " via " $3 " dev " $5}' ``` Additional inventory operations include: ```bash tailscale status tailscale ip systemctl list-units --type=service --state=running docker ps ss -tuln mount du -sh /home/*/ ``` ### Technical Analysis The information-gathering behavior is declared in `SKILL.md` and no code was found that transmits the collected data externally. It is therefore not covert exfiltration. Nevertheless, the `all` command combines hostnames, IP and MAC addresses, DNS and routing configuration, Tailscale addresses and peers, active services, Docker containers, listening ports, mounts, and user-home storage information into one output stream. This collection exceeds minimum disclosure for a basic system health check. If agent output, command logs, support transcripts, or API responses are visible to an untrusted party, the resulting dataset provides ...[truncated 1045 chars]
Remediation
## Remediation Suggestions - Make the default overview minimal and redact MAC addresses, VPN peer details, DNS servers, routes, and listening addresses. - Require explicit subcommands or flags for sensitive inventory such as Tailscale peers, Docker workloads, listeners, and home-directory usage. - Avoid including `/home/*` information unless storage analysis is specifically requested. - Restrict Skill invocation and transcript access to trusted administrators. - Avoid persisting command output, or apply retention controls and output redaction before logging. - Document the sensitivity of `skill.sh all` and require affirmative confirmation before producing the complete inventory.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The skill is presented as general Raspberry Pi administration, but the documented behavior goes beyond routine monitoring into service-specific process killing/restarting, launching a user-scoped application from a hardcoded path, exposing service endpoints, and applying persistent system configuration changes. This mismatch is dangerous because users or orchestrators may grant broad trust based on the benign description while the skill can materially alter host state and availability.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The script's dry-run output, startup messages, and connection details inconsistently reference ports 18789 and 18790, while the actual command starts the gateway on 18789. In a system administration skill, this can cause operators to connect to or firewall the wrong port, mis-verify service health, and make unsafe maintenance decisions during restart or incident response.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This wrapper exposes maintenance actions including update, clean, reboot, and restart-gateway directly from a single entrypoint without any confirmation prompt, privilege check, or contextual warning. In an agent-driven environment, this increases the chance of accidental or unauthorized disruptive execution, especially for commands that can reboot the device or interrupt connectivity.

Session Persistence

Medium
Category
Rogue Agent
Content
if [ "$(systemctl is-enabled bluetooth.service)" = "disabled" ]; then
    echo "Enabling Bluetooth..."
    $SUDO systemctl enable bluetooth.service
    echo "✅ Bluetooth enabled"
  fi
Confidence
75% confidence
Finding
Enabling bluetooth.service makes the service persist across reboots, which qualifies as a persistence-related system change. In this script it is presented as explicit undo functionality, so it is not malicious, but it still changes boot-time behavior and could unexpectedly expose Bluetooth attack surface if run on systems where it was intentionally disabled for security.

Session Persistence

Medium
Category
Rogue Agent
Content
if [ "$(systemctl is-enabled ModemManager.service)" = "disabled" ]; then
    echo "Enabling ModemManager..."
    $SUDO systemctl enable ModemManager.service
    echo "✅ ModemManager enabled"
  fi
Confidence
76% confidence
Finding
systemctl enable ModemManager.service persists the service across reboots and therefore changes system startup behavior. While framed as rollback, it may re-enable modem-related functionality that an administrator had intentionally disabled outside this script, increasing connectivity and attack surface unexpectedly.

Session Persistence

Medium
Category
Rogue Agent
Content
if [ "$(systemctl is-enabled avahi-daemon.service)" = "disabled" ]; then
    echo "Enabling Avahi..."
    $SUDO systemctl enable avahi-daemon.service
    echo "✅ Avahi enabled"
  fi
Confidence
78% confidence
Finding
Enabling avahi-daemon.service persists multicast DNS/service discovery at boot, which broadens network visibility and attack surface. In context this is intended as undo logic, but it is still risky because the script does not track whether Avahi was disabled by the script or by prior hardening decisions.

Static analysis

No suspicious patterns detected.