Back to skill

Security audit

VPS Agent Migration

Security checks for vulnerabilities and agentic risk

Overview

This migration guide is coherent but uses unsafe root SSH, disables host verification, and exposes Discord/VPS secrets in commands.

Review this skill carefully before installing or using it. If you proceed, replace password-based root SSH with a verified SSH key and a limited account, remove StrictHostKeyChecking=no, avoid printing or embedding Discord tokens in shell commands, do a dry-run and allowlist the files to transfer, back up openclaw.json, and prepare a rollback before restarting gateways or disabling the local account.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:22
Finding
Insecure SSH Password Handling and Disabled Host Verification<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 22, 26-27, 40-53, 58, and 64 **Vulnerability Type**: Insecure command-line credential handling and SSH host verification bypass **Risk Level**: High ### Vulnerable Code ```bash # Line 22 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP ``` ```bash # Lines 26-27 rsync -avz --exclude='sessions' --exclude='.DS_Store' --exclude='memory.md' \ ~/.openclaw/agents/[agent名]/ root@VPS_IP:/root/.openclaw/agents/[agent名]/ ``` ```bash # Lines 40-53 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP 'python3 -c " import json with open(\"/root/.openclaw/openclaw.json\") as f: data = json.load(f) data[\"channels\"][\"discord\"][\"accounts\"][\"[Discord_ID]\"] = { \"name\": \"[Agent名字]\", \"enabled\": True, \"token\": \"[Token]\", \"groupPolicy\": \"allowlist\", \"streaming\": \"off\" } with open(\"/root/.openclaw/openclaw.json\", \"w\") as f: json.dump(data, f, indent=2) "' ``` ```bash # Line 58 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP 'openclaw config set bindings \"[{\\\"agentId\\\":\\\"[agentId]\\\",\\\"match\\\":{\\\"channel\\\":\\\"discord\\\",\\\"accountId\\\":\\\"[Discord_ID]\\\"}}]\"' ``` ```bash # Line 64 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP "openclaw gateway restart" ``` ### Technical Analysis The skill recommends placing the VPS password directly in the `sshpass -p` command-line argument. Depending on the environment, command-line secrets can be exposed through shell history, process inspection, terminal logging, debugging output, or automation logs. The explicit `StrictHostKeyChecking=no` option disables verification of the remote server's identity. This removes an essential SSH security boundary and allows a network-positioned attacker to impersonate the VPS. Because the connection is also used for privileged configuration changes and transmission of agent data and Discord credential ...[truncated 1695 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace password-based root authentication with a dedicated SSH key protected by an appropriate passphrase or managed identity. - Do not use `sshpass -p` or place credentials in command-line arguments. - Remove `StrictHostKeyChecking=no`. - Provision and verify the VPS host key in `known_hosts` before migration. For automation, use a dedicated known-hosts file and fail closed on mismatches. - Connect through a dedicated, non-root migration account with narrowly scoped `sudo` permissions for only the required OpenClaw operations. - Disable direct root SSH login and disable password authentication where operationally possible. - Ensure shell tracing is disabled while handling secrets and prevent migration commands from being recorded in shared logs. - Rotate any password that has already been used through the documented command-line pattern. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:31
Finding
Discord Bot Token Exposed Through Terminal Output and Inline Commands<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 31-35 and 40-53 **Vulnerability Type**: Plaintext secret exposure **Risk Level**: High ### Vulnerable Code ```bash # Lines 31-35 # Step 2: 获取本地 Discord Token 从本地 `~/.openclaw/openclaw.json` 中查找对应 Agent 的 token: ```bash cat ~/.openclaw/openclaw.json | grep -A5 '"[Discord_ID]":' ``` ``` ```bash # Lines 40-53 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP 'python3 -c " import json with open(\"/root/.openclaw/openclaw.json\") as f: data = json.load(f) data[\"channels\"][\"discord\"][\"accounts\"][\"[Discord_ID]\"] = { \"name\": \"[Agent名字]\", \"enabled\": True, \"token\": \"[Token]\", \"groupPolicy\": \"allowlist\", \"streaming\": \"off\" } with open(\"/root/.openclaw/openclaw.json\", \"w\") as f: json.dump(data, f, indent=2) "' ``` ### Technical Analysis The first command prints the matching Discord account entry and five following lines from `openclaw.json`. Since the documented purpose is to retrieve the token, this output is expected to reveal the plaintext Discord bot token in the terminal. It may also reveal adjacent account configuration. The following migration step requires substituting the token into an inline SSH and Python command. The resulting secret may consequently appear in shell history, process arguments, terminal recordings, CI/CD logs, clipboard history, troubleshooting transcripts, or audit logs. Although the token must ultimately be available to OpenClaw, exposing it interactively and embedding it in a command line is unnecessary. Secrets should be transmitted through a protected secret channel and written with restrictive permissions without being displayed. ### Attack Path 1. An administrator runs the documented `grep -A5` command. 2. The Discord token is printed to the terminal and may be captured by terminal logging, screen sharing, session recording, or copied into a transcript. 3. The administrator substitutes th ...[truncated 939 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not print the token to the terminal or retrieve it with `grep -A5`. - Use a secret manager or protected deployment mechanism to inject the token at the destination. - If direct transfer is required, read the exact JSON value programmatically and pass it through protected standard input rather than a command-line argument. - Avoid command interpolation that embeds the token in SSH, Python, or OpenClaw process arguments. - Disable shell tracing and ensure deployment tooling redacts sensitive fields. - Store `openclaw.json` with ownership limited to the OpenClaw service account and permissions such as `0600`. - Avoid copying tokens through clipboards, chat messages, tickets, or terminal transcripts. - Rotate Discord tokens that may already have been exposed through this workflow and update both local and remote configuration securely. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:26
Finding
Migration Uses Root Privileges and an Overly Broad File Transfer<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 26-27 and 40-53 **Vulnerability Type**: Excessive privileges and insufficiently constrained data migration **Risk Level**: Medium ### Vulnerable Code ```bash # Lines 26-27 rsync -avz --exclude='sessions' --exclude='.DS_Store' --exclude='memory.md' \ ~/.openclaw/agents/[agent名]/ root@VPS_IP:/root/.openclaw/agents/[agent名]/ ``` ```bash # Lines 40-53 sshpass -p 'VPS密码' ssh -o StrictHostKeyChecking=no root@VPS_IP 'python3 -c " import json with open(\"/root/.openclaw/openclaw.json\") as f: data = json.load(f) data[\"channels\"][\"discord\"][\"accounts\"][\"[Discord_ID]\"] = { \"name\": \"[Agent名字]\", \"enabled\": True, \"token\": \"[Token]\", \"groupPolicy\": \"allowlist\", \"streaming\": \"off\" } with open(\"/root/.openclaw/openclaw.json\", \"w\") as f: json.dump(data, f, indent=2) "' ``` ### Technical Analysis The migration transfers almost the entire local agent directory to the remote root account. Only `sessions`, `.DS_Store`, and `memory.md` are excluded. This denylist approach does not prevent other sensitive or unnecessary files—such as credentials, private prompts, environment files, caches, keys, or generated state—from being transferred if they are present in the agent directory. The destination and all configuration operations use the `root` account. Agent migration and OpenClaw configuration generally do not require unrestricted system-wide privileges. Using root violates least-privilege principles and increases the blast radius of operator error, compromised credentials, malicious source files, or command manipulation. ### Attack Path 1. A sensitive file not covered by the three exclusion patterns is present under the selected local agent directory. 2. The broad `rsync` command copies that file to `/root/.openclaw/agents/[agent name]/` on the VPS. 3. An attacker who compromises the VPS root account, intercepts the insecurely verified SSH destin ...[truncated 800 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a dedicated OpenClaw service or migration account and make it the owner of the relevant OpenClaw directories. - Disable direct root login and grant only narrowly scoped `sudo` permissions when a privileged restart is unavoidable. - Replace the exclusion-based transfer with an explicit allowlist of files required to operate the agent. - Generate and review an `rsync --dry-run` manifest before performing the actual migration. - Exclude secrets, caches, runtime state, private keys, environment files, and local-only metadata unless each item is explicitly required. - Apply restrictive destination ownership and permissions immediately after transfer. - Use a staging directory and validate file names, types, symlinks, and permissions before deploying files into the active agent directory. - Document the minimum required migration artifacts rather than copying the full agent directory by default. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (4)

Missing User Warnings

High
Confidence
99% confidence
Finding
Using StrictHostKeyChecking=no disables SSH server identity verification and allows man-in-the-middle interception or redirection to a rogue host. Because the same step also carries administrative access and later moves sensitive agent files and tokens, an attacker on the network could capture credentials, tamper with migrated files, or install a malicious configuration on the VPS.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
Using StrictHostKeyChecking=no disables SSH server identity verification and allows man-in-the-middle interception or redirection to a rogue host. Because the same step also carries administrative access and later moves sensitive agent files and tokens, an attacker on the network could capture credentials, tamper with migrated files, or install a malicious configuration on the VPS.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The guide performs live configuration edits, binding changes, account disablement, and gateway restarts without warning about service interruption, misrouting, or rollback procedures. A mistake in agent ID, Discord ID, or bindings could disable the local bot, break production routing, or leave the remote bot misconfigured, causing loss of availability or unintended behavior. The context makes this somewhat more dangerous because the actions affect running automation accounts and root-owned service configuration.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The file presents the description and operational instructions in Chinese only, which effectively forces a specific language for users of the skill. There is no indication of user opt-in, alternative language availability, or justification for a Chinese-only locale.

Static analysis

No suspicious patterns detected.