T03 · Remote Payload Retrieval and Execution
- Location
scripts/install_openclaw_remote.sh:323- Finding
Unverified Remote Installer Scripts Are Executed Directly
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill does perform the advertised remote OpenClaw installation work, but it uses risky SSH and installer practices that users should review before running it.
Review this before installing on production hosts. Prefer key-based SSH with verified known_hosts, avoid password mode and inline API keys, use secret references, pin versions or image digests, and do not run the curl-to-bash installer paths unless you trust the live upstream scripts and deployment channel.
scripts/install_openclaw_remote.sh:323Unverified Remote Installer Scripts Are Executed Directly
scripts/configure_openclaw_remote.py:17Shell Command Injection Through Untrusted Configuration Values
scripts/install_openclaw_remote.sh:143SSH Server Identity Verification Is Disabled
scripts/configure_openclaw_remote.py:62SSH Passwords and Provider API Keys Are Exposed in Process Arguments and Output
This mismatch hides materially dangerous behaviors such as password-based SSH, disabled host key verification, and execution of remote scripts fetched over the network. When documentation omits or downplays those actions, users may authorize the skill without understanding that it can expose credentials, enable MITM attacks, and run untrusted code on remote systems.
This mismatch hides materially dangerous behaviors such as password-based SSH, disabled host key verification, and execution of remote scripts fetched over the network. When documentation omits or downplays those actions, users may authorize the skill without understanding that it can expose credentials, enable MITM attacks, and run untrusted code on remote systems.
This remote-install skill is especially dangerous because it is explicitly designed to connect to external systems over SSH and execute administrative commands. Using shell=True with attacker-influenced parameters in this context turns the script into a potential command-execution primitive against the operator machine, and the broad deployment context increases blast radius across multiple hosts.
def run_ssh_command(ssh_cmd: str, command: str) -> tuple[str, str, int]:
"""Execute command via SSH and return stdout, stderr, returncode."""
full_cmd = f"{ssh_cmd} '{command}'"
result = subprocess.run(
full_cmd, shell=True, capture_output=True, text=True
)
return result.stdout, result.stderr, result.returncode
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Examples:
# Auto-detect best method
$0 root@server.com user ~/.ssh/id_rsa
# Async installation with monitoring
$0 root@server.com user ~/.ssh/id_rsa --async
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Examples:
# Auto-detect best method
$0 root@server.com user ~/.ssh/id_rsa
# Async installation with monitoring
$0 root@server.com user ~/.ssh/id_rsa --async
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Examples:
# Auto-detect best method
$0 root@server.com user ~/.ssh/id_rsa
# Async installation with monitoring
$0 root@server.com user ~/.ssh/id_rsa --async
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Examples:
# Auto-detect best method
$0 root@server.com user ~/.ssh/id_rsa
# Async installation with monitoring
$0 root@server.com user ~/.ssh/id_rsa --async
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Examples:
# Auto-detect best method
$0 root@server.com user ~/.ssh/id_rsa
# Async installation with monitoring
$0 root@server.com user ~/.ssh/id_rsa --async
The script fetches https://openclaw.ai/install-cli.sh and pipes it directly to bash on the remote host. This gives the remote content full code-execution privileges during installation; if the host, CDN, TLS chain, DNS, or upstream script is compromised, an attacker can execute arbitrary commands on target servers at scale.
cli|install-cli)
log_info "Preparing install-cli.sh installation..."
install_cmd="curl -fsSL https://openclaw.ai/install-cli.sh | bash -s -- --version $VERSION"
if [[ "$NON_INTERACTIVE" == "true" ]]; then
install_cmd="$install_cmd --no-onboard"
fi
The main installer path downloads https://openclaw.ai/install.sh and executes it directly with bash, creating an unverified remote code execution path on every target system. Because this skill is explicitly for one-click remote deployment across servers, the blast radius is high: a single upstream compromise could lead to broad fleet compromise.
installer|*)
log_info "Preparing installer script installation..."
install_cmd="curl -fsSL https://openclaw.ai/install.sh | bash -s --"
if [[ "$VERSION" != "latest" ]]; then
install_cmd="$install_cmd --version $VERSION"
fi
The skill advertises and documents shell-based remote installation behavior but does not declare any explicit tool scope or permissions boundary. That increases the chance that an agent or reviewer will underestimate its ability to execute commands against local or remote systems, which is especially risky for an SSH-based installer.
The documentation promotes one-click remote installation and automation without a clear warning that it will make changes to the target machine. In the context of an SSH installer, that omission is risky because users may invoke it on production hosts without realizing it performs privileged or persistent system modifications.
Documenting password-based remote installation without strong credential-handling warnings normalizes a weaker authentication path for administrative access. In this context, passwords may be exposed via shell history, process arguments, logs, or automation systems, making remote compromise more likely if operational hygiene is poor.
Offering plaintext secret storage as an option without a prominent warning can lead users to persist API keys directly in configuration files. In a remote-install/configuration workflow, that raises the chance of credential leakage through backups, logs, file sharing, or host compromise.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Check key permissions
chmod 600 ~/.ssh/id_rsa
# Add to ssh-agent
ssh-add ~/.ssh/id_rsa
The script constructs a shell command by concatenating ssh_cmd and a quoted remote command, then executes it with subprocess.run(..., shell=True). Because multiple inputs that feed ssh_cmd and command are user-controlled and not robustly shell-escaped across both local and remote shell contexts, this creates command-injection risk on the local machine and potentially malformed execution on the remote host.
def run_ssh_command(ssh_cmd: str, command: str) -> tuple[str, str, int]:
"""Execute command via SSH and return stdout, stderr, returncode."""
full_cmd = f"{ssh_cmd} '{command}'"
result = subprocess.run(
full_cmd, shell=True, capture_output=True, text=True
)
return result.stdout, result.stderr, result.returncode
The script prints the full generated openclaw onboard command, and in plaintext mode that command includes the API key inline. This can leak credentials to terminal history, logs, CI output, monitoring systems, or other users with access to the process/session output.
The docstring for update_config_file states that it will update the OpenClaw config file directly. In reality, the implementation only retrieves the current config, prints it along with the requested updates, and explicitly notes that direct update is just a placeholder, so the documented intent contradicts actual behavior.
The script accepts an SSH password and embeds it directly in an sshpass -p ... command string. Even with quoting, putting secrets on the command line risks exposure through process listings, shell history, audit logs, crash reports, and other system telemetry.
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.
LOG_DIR="$HOME/.openclaw/remote-install-logs/${host_safe}_${timestamp}"
fi
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/install.log"
# Create symlink to latest
For password-based authentication, the script constructs an sshpass -p '...password...' command string and later executes it. Supplying secrets on the command line exposes them to local process listing, shell history/logging risks, and quoting/injection issues if the password contains shell metacharacters; this is made more dangerous by the script's remote-admin use case.
The code logs Installing Docker first... and sets install_cmd to a Docker installer, but then immediately overwrites install_cmd with docker run ..., so Docker is never actually installed in this branch. The comment/log intent contradicts the effective behavior, which assumes Docker is already present.
The Docker deployment uses a floating image reference (openclawai/openclaw:latest) rather than a pinned digest or immutable version. This allows unexpected or malicious upstream image changes to be pulled during remote installation, which is especially risky because the script is intended for unattended deployment onto remote servers.
This script performs safety-impacting remote actions including package installation, container startup, execution of curl-piped installer scripts, and optional remote configuration. While it logs progress, it does not clearly warn the user that it will modify the remote system, fetch and execute remote scripts, and potentially change services or packages before proceeding.
The script includes a curl ... | sh pattern to install Docker from a remote URL with no signature or checksum verification. Even though the current control flow appears to overwrite this command later, the pattern is inherently dangerous and could lead to arbitrary code execution on the remote host if used or reintroduced; in a remote installer context, this materially raises supply-chain risk.
# Check if Docker is available
if ! $SSH_CMD "command -v docker &> /dev/null" 2>/dev/null; then
log_info "Installing Docker first..."
install_cmd="curl -fsSL https://get.docker.com | sh"
fi
# Run OpenClaw Docker
install_cmd="docker run -d --name openclaw \
No suspicious patterns detected.