Back to skill

Security audit

Claw Time Machine

Security checks for vulnerabilities and agentic risk

Overview

This is a real OpenClaw backup and migration tool, but it handles credentials and remote restore commands in ways that need careful review before use.

Install only if you trust the publisher and need full OpenClaw state backup or migration. Treat every backup as a sensitive secrets bundle, store it privately, do not restore archives from untrusted sources, avoid --force unless automation is intentional, do not use untrusted --remote-dir values, and prefer fixing the remote-script quoting, archive validation, and file-permission controls before production use.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ctm.sh:361
Finding
Remote Command Injection Through the --remote-dir Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ctm.sh`, lines 311 and 361-368 **Vulnerability Type**: Shell command injection through unsafe source-code generation **Risk Level**: High ### Vulnerable Code ```bash remote_script=$(cat <<'EOS' set -euo pipefail REMOTE_DIR="__REMOTE_DIR__" ARCHIVE="__ARCHIVE__" FORCE="__FORCE__" CLEAN_REMOTE_ARCHIVE="__CLEAN_REMOTE_ARCHIVE__" ``` ```bash remote_script=${remote_script//__REMOTE_DIR__/$REMOTE_DIR} remote_script=${remote_script//__ARCHIVE__/~\/$filename} remote_script=${remote_script//__FORCE__/$FORCE} remote_script=${remote_script//__CLEAN_REMOTE_ARCHIVE__/$CLEAN_REMOTE_ARCHIVE} log_info "在目标服务器执行恢复..." ssh "$target_host" "bash -s" <<< "$remote_script" ``` ### Technical Analysis The value supplied through `--remote-dir` is stored in `REMOTE_DIR` and inserted directly into generated Bash source code. The replacement is not shell-escaped or constrained to a safe path syntax. Although the template places the placeholder inside double quotes, an attacker can include a double quote followed by shell syntax in the argument. The substituted text can terminate the assignment and append arbitrary commands. The resulting script is sent to the target host and interpreted by `bash -s`. This is a source-code injection vulnerability rather than ordinary argument injection: user-controlled data is converted into executable shell syntax before being passed to Bash. ### Attack Path 1. An attacker supplies or persuades an operator to use a crafted `--remote-dir` value containing a quote, command syntax, and a comment or equivalent suffix. 2. `parse_args` accepts that value without path validation. 3. The migration function replaces `__REMOTE_DIR__` in the generated script with the attacker-controlled value. 4. The crafted value breaks out of the `REMOTE_DIR="..."` assignment. 5. The complete generated script is transmitted through SSH. 6. `bash -s` evaluates the injected command on the target host under the au ...[truncated 603 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not construct executable shell source by replacing placeholders with untrusted values. 1. Pass the remote directory to the remote script as a positional argument or environment value rather than embedding it in the script. 2. If source generation cannot be avoided, quote every substituted value using a robust mechanism such as `printf '%q'`. 3. Validate `--remote-dir` against an explicit path policy. Reject control characters, newlines, shell metacharacters, and unsupported path forms. 4. Preserve argument boundaries when invoking the remote script. 5. Add tests using values containing quotes, semicolons, command substitutions, newlines, spaces, and leading hyphens. A safer design is conceptually: ```bash ssh "$target_host" bash -s -- "$REMOTE_DIR" "~/$filename" "$FORCE" "$CLEAN_REMOTE_ARCHIVE" <<'EOS' set -euo pipefail REMOTE_DIR="$1" ARCHIVE="$2" FORCE="$3" CLEAN_REMOTE_ARCHIVE="$4" # Restoration logic follows without evaluating these values as shell source. EOS ``` The remote values must still be validated before they are used as filesystem destinations. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ctm.sh:183
Finding
Sensitive Backup Archives Are Created Without Enforced Private Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ctm.sh`, lines 183-206; related directory creation at lines 72-74 **Vulnerability Type**: Insecure permissions for archives containing credentials and identity data **Risk Level**: Medium ### Vulnerable Code ```bash ensure_backup_dir() { mkdir -p "$BACKUP_DIR" } ``` ```bash backup() { require_cmd tar mktemp du cp ensure_backup_dir local output_name="${BACKUP_FILE:-$(generate_filename)}" local output_file="$BACKUP_DIR/$output_name" local manifest bundle_dir manifest=$(create_manifest) if [[ ! -s "$manifest" ]]; then rm -f "$manifest" die "没有找到可备份的 OpenClaw 状态路径: $OPENCLAW_DIR" fi if (( DRY_RUN == 1 )); then log_info "Dry run: 将备份以下路径" sed 's/^/ - /' "$manifest" rm -f "$manifest" return 0 fi bundle_dir=$(mktemp -d) while IFS= read -r item; do mkdir -p "$bundle_dir/$(dirname "$item")" cp -a "$OPENCLAW_DIR/$item" "$bundle_dir/$item" done < "$manifest" build_manifest_file "$manifest" "$bundle_dir" log_info "正在创建备份: $output_file" tar czf "$output_file" -C "$bundle_dir" . ``` ### Technical Analysis The backup explicitly includes sensitive paths such as `credentials`, `telegram`, `identity`, and `openclaw.json`. However, the script does not set a restrictive process umask, enforce mode `0700` on the backup directory, or enforce mode `0600` on the resulting archive. Consequently, archive accessibility depends on the invoking environment's umask and on the permissions of any pre-existing backup directory. Under a permissive configuration, the archive can become readable by other local users. The migration workflow also copies the sensitive archive into the remote account's home directory and keeps it there by default. Compression does not provide confidentiality, and the archive is not encrypted. ### Attack Path 1. The script is run in an environment with a permissive umask or a pre-existing `BACKUP_DIR` that is accessible to othe ...[truncated 1194 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set a restrictive umask near the beginning of the script before creating any sensitive file: ```bash umask 077 ``` 2. Create and verify the backup directory with owner-only permissions: ```bash mkdir -p -- "$BACKUP_DIR" chmod 700 -- "$BACKUP_DIR" ``` 3. Explicitly enforce archive permissions after creation: ```bash chmod 600 -- "$output_file" ``` 4. On the target host, immediately enforce mode `0600` after SCP transfer and remove the archive after a successful restore by default. 5. Warn operators when retaining a credential-bearing archive remotely. 6. Consider authenticated encryption for archives that will be retained, transported through less-trusted systems, or stored outside an encrypted filesystem. 7. Reject a backup directory owned by another user or writable by untrusted users. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ctm.sh:264
Finding
Restore Extracts Untrusted Archives Without Content or Authenticity Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ctm.sh`, lines 264-277; equivalent remote behavior at lines 327-348 **Vulnerability Type**: Unsafe restoration of unrestricted and unauthenticated archive content **Risk Level**: Medium ### Vulnerable Code ```bash restore() { require_cmd tar [[ -n "$BACKUP_FILE" ]] || die "请指定备份序号、文件名或 latest" local full_path full_path=$(resolve_backup_file "$BACKUP_FILE") || die "备份文件不存在: $BACKUP_FILE" [[ -f "$full_path" ]] || die "备份文件不存在: $full_path" tar tzf "$full_path" >/dev/null confirm_or_exit "这会覆盖当前 OpenClaw 保留状态路径" mkdir -p "$OPENCLAW_DIR" create_safety_backup log_info "清理现有保留状态..." remove_soul_items log_info "从备份恢复: $full_path" tar xzf "$full_path" -C "$OPENCLAW_DIR" ``` The remote migration script repeats the same extraction pattern: ```bash mkdir -p "$REMOTE_DIR" tar tzf "$ARCHIVE" >/dev/null if ! confirm_or_exit "Remote restore will overwrite preserved state in $REMOTE_DIR"; then echo "Cancelled" exit 1 fi if [ -d "$REMOTE_DIR" ]; then mkdir -p "$SAFETY_DIR" for item in $SOUL_ITEMS; do if [ -e "$REMOTE_DIR/$item" ]; then mkdir -p "$SAFETY_DIR/$(dirname "$item")" cp -a "$REMOTE_DIR/$item" "$SAFETY_DIR/$item" fi done fi for item in $SOUL_ITEMS; do if [ -e "$REMOTE_DIR/$item" ]; then rm -rf -- "$REMOTE_DIR/$item" fi done tar xzf "$ARCHIVE" -C "$REMOTE_DIR" ``` ### Technical Analysis `tar tzf` only confirms that the input can be parsed as a gzip-compressed tar archive. It does not establish that the archive: - Was produced by this Skill. - Has not been altered. - Contains only the documented top-level paths. - Contains safe member names and file types. - Matches a trusted or signed manifest. - Excludes malicious skills, scheduled-task state, symbolic links, hard links, device entries, or other unexpected content. After this minimal format check, the script deletes the existing preserved state and extracts every archive member d ...[truncated 2287 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Implement a staged and authenticated restoration process: 1. Extract the archive into a newly created private staging directory rather than directly into the live OpenClaw directory. 2. Enumerate archive members before extraction and reject: - Absolute paths. - `..` traversal components. - Paths outside the documented top-level allowlist. - Symbolic links and hard links unless explicitly required and safely validated. - Device nodes, FIFOs, sockets, and other special files. - Duplicate or otherwise ambiguous member paths. 3. Permit only the documented top-level entries: - `workspace` - `credentials` - `telegram` - `skills` - `cron` - `openclaw.json` - `identity` - `manifest.txt` 4. Validate the staged filesystem after extraction, including resolved paths, ownership, file types, and permissions. 5. Add cryptographic integrity and provenance verification, preferably using a signed manifest or authenticated archive format. A checksum stored only inside the same archive is insufficient against malicious replacement. 6. Copy only validated allowlisted paths from staging into the destination. 7. Preserve the existing state until staging and all validation steps succeed, then perform the replacement as atomically as practical. 8. Apply the same validation procedure to both local restore and remote migration. 9. Clearly warn operators that restoring archives from untrusted sources can install executable skills and scheduled-task state. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
local item
  for item in "${SOUL_FILES[@]}"; do
    if [[ -e "$OPENCLAW_DIR/$item" ]]; then
      rm -rf -- "$OPENCLAW_DIR/$item"
    fi
  done
}
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
for item in $SOUL_ITEMS; do
  if [ -e "$REMOTE_DIR/$item" ]; then
    rm -rf -- "$REMOTE_DIR/$item"
  fi
done
Confidence
95% confidence
Finding
The remote restore script performs rm -rf on paths derived from the user-controlled --remote-dir value after simple string substitution into a shell script. If REMOTE_DIR is set to a dangerous location such as /, $HOME, or a path containing shell metacharacters, the generated remote script can delete unintended files or execute injected commands on the remote host during migration.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The activation description is broad enough to trigger on very common terms like backup, restore, migration, and generic Chinese equivalents. That can cause the skill to activate in contexts where the user did not intend to invoke a highly privileged state-management tool, increasing the chance of destructive restore or data-exfiltrating migration actions being suggested or run.

Session Persistence

Medium
Category
Rogue Agent
Content
Commands:

- `backup [filename]` — create a backup under `~/.ctm/`
- `list` — show backups, newest first
- `restore <index|filename|latest> [--force]` — restore a backup
- `migrate <user@host> [--remote-dir <dir>] [--clean-remote-archive] [--force]` — copy a backup to another machine and restore it there
Confidence
92% confidence
Finding
The skill is explicitly designed to persist and archive sensitive session and installation state, including credentials, identity, workspace memories, and custom skills, into backups under a user directory and to migrate them to remote hosts. This materially increases exposure of secrets at rest and in transit, especially if backup permissions, encryption, retention, or destination trust are not tightly controlled.

Session Persistence

Medium
Category
Rogue Agent
Content
High-level sequence:

1. Create a fresh backup on the source machine
2. Copy the archive to the target machine
3. Ensure `~/.openclaw` exists on the target machine
4. Create a safety backup of target state paths if they exist
Confidence
60% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
$SCRIPT_NAME migrate <user@host> [--remote-dir <dir>] [--clean-remote-archive] [--force]

Commands:
  backup     Create a backup in $BACKUP_DIR
  list       List backups, newest first
  restore    Restore by index, filename, or 'latest'
  migrate    Create a fresh backup, copy it to a remote host, and restore there
Confidence
91% confidence
Finding
The script is explicitly designed to back up and migrate highly sensitive state, including credentials, identity, workspace memory, skills, and scheduled tasks. In this skill context, preserving and exporting that material increases risk because the resulting tar.gz archives are not encrypted, are copied to a predictable backup directory, and are transferred to remote hosts, creating a concentrated secrets bundle that could be stolen or misused if local or remote storage is compromised.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
This shell script includes user-facing operational messages in Chinese, such as dependency and error output, without any indication that language is configurable or selected by user preference. That can violate a language/locale policy when a skill is expected to respect user locale or offer opt-in.

Static analysis

No suspicious patterns detected.