T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/schedule-uninstall.sh:43
- Finding
- Host Command Injection Through Notification Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/schedule-uninstall.sh`, lines 43–51 and 89–94 **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code ```bash # Build command string for one-shot ARG_STR="" for a in "${EXTRA_ARGS[@]}"; do ARG_STR="$ARG_STR '$a'" done CMD="sleep $DELAY && '$UNINSTALL_SCRIPT' $ARG_STR" case "$(uname -s)" in Darwin) if launchctl submit -l openclaw-uninstall -o "$LOG_FILE" -e "$LOG_FILE" -- \ /bin/bash -c "$CMD" 2>/dev/null; then ``` The same unsafe command string is passed to the Linux execution paths: ```bash if systemd-run --user --onetime --unit=openclaw-uninstall \ /bin/bash -c "$CMD" &>/dev/null; then echo "Linux uninstall scheduled (systemd), will run in ~${DELAY}s." else # Fallback: nohup + disown (works when systemd-run unavailable, e.g. WSL2 without systemd) (nohup bash -c "$CMD" >> "$LOG_FILE" 2>&1 &) ``` ### Technical Analysis Values supplied through `--notify-email` and `--notify-ntfy` are appended to a command string between single quotes. The script does not escape embedded single quotes before passing the result to `bash -c`. Shell metacharacters placed after an embedded quote are consequently interpreted as command syntax rather than as part of a notification argument. Array usage while initially collecting the arguments does not protect the values because the array is later converted back into an unsafe shell command string. The Skill documentation explicitly requires this scheduler to run on the gateway host rather than in a sandbox. Exploitation therefore results in command execution directly on that host with the privileges of the user running the Agent. ### Attack Path 1. An attacker persuades the user or Agent to request an ntfy topic or email value containing shell syntax, such as: ```text x'; touch /tmp/openclaw-injected; #' ``` 2. The Agent invokes: ```bash ./scripts/schedule-uninstall.sh --notify-ntfy "x'; to ...[truncated 795 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not serialize arguments into a command string passed to `bash -c`. - Create a dedicated wrapper that sleeps and then invokes the uninstall script using an argument array. - Where service APIs require separate arguments, supply each argument directly rather than through a shell interpreter. - If serialization is unavoidable, quote every argument using a robust mechanism such as `printf '%q'`; direct argument passing remains preferable. - Validate notification values before scheduling: - Enforce a conservative email-address format. - Restrict ntfy topics to an documented allowlist of characters and lengths. - Reject control characters, shell metacharacters, embedded URLs, and path separators where they are unnecessary. - Reject unknown options and detect missing option values instead of silently shifting arguments. - Add regression tests using quotes, semicolons, command substitutions, newlines, and redirection operators. ]]>
