Back to skill

Security audit

OC Migrator

Security checks for vulnerabilities and agentic risk

Overview

This migration skill does what it says broadly, but its restore and backup handling can overwrite persistent agent state and expose sensitive backups without enough safeguards.

Install only if you are comfortable with a migration script that can copy sensitive OpenClaw config, memory, scripts, and skills into and out of your live environment. Use only backups you created and transferred through trusted channels, avoid --no-encrypt for sensitive data, do not reuse the backup password, and consider manually staging or inspecting an archive before restoring because existing agent state may be overwritten.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Error
Location
scripts/migrate.sh:185
Finding
Unauthenticated Backup Restoration Can Poison Persistent Agent State<![CDATA[ ## Vulnerability Details **File Location**: `scripts/migrate.sh:185-234` **Vulnerability Type**: Unauthenticated restoration of instruction-bearing Agent state **Risk Level**: High ### Vulnerable Code ```bash TMPDIR=$(mktemp -d) if echo "$BACKUP_FILE" | grep -q "\.enc$"; then if [ -n "${MIGRATE_PASSWORD:-}" ]; then PASS="$MIGRATE_PASSWORD" else echo -n " 🔑 Enter decryption password: " read -s PASS echo "" fi openssl enc -aes-256-cbc -d -salt -pbkdf2 -pass "pass:$PASS" -in "$BACKUP_FILE" | tar -xzf - -C "$TMPDIR" else tar -xzf "$BACKUP_FILE" -C "$TMPDIR" fi RESTORE_DIR=$(ls -d "$TMPDIR"/openclaw-export-* 2>/dev/null | head -1) if [ -z "$RESTORE_DIR" ]; then echo "❌ Invalid backup format" rm -rf "$TMPDIR" exit 1 fi # Show manifest if [ -f "$RESTORE_DIR/manifest.json" ]; then echo " 📋 Backup from: $(cat "$RESTORE_DIR/manifest.json")" fi # Restore config if [ -d "$RESTORE_DIR/config" ]; then echo " → Restoring config" cp "$RESTORE_DIR/config/openclaw.json" "$OC_HOME/openclaw.json" 2>/dev/null && echo " ✅ openclaw.json" chmod 600 "$OC_HOME/openclaw.json" if [ -d "$RESTORE_DIR/config/agents" ]; then cp -R "$RESTORE_DIR/config/agents/"* "$OC_HOME/agents/" 2>/dev/null && echo " ✅ agents/" find "$OC_HOME/agents" -name "*.json" -exec chmod 600 {} \; fi fi # Restore workspace if [ -d "$RESTORE_DIR/workspace" ]; then echo " → Restoring workspace" for f in "$RESTORE_DIR/workspace"/*.md; do [ -f "$f" ] && cp "$f" "$OC_WORKSPACE/" && echo " ✅ $(basename $f)" done for dir in memory knowledge .learnings scripts skills; do if [ -d "$RESTORE_DIR/workspace/$dir" ]; then mkdir -p "$OC_WORKSPACE/$dir" cp -R "$RESTORE_DIR/workspace/$dir/"* "$OC_WORKSPACE/$dir/" 2>/dev/null && echo " ✅ $dir/" fi done fi ``` ### Technical Analysis The restore operation accepts a user-supplied archive and installs its contents into the active OpenClaw configuration and workspace wi ...[truncated 2080 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Digitally sign every backup with a trusted signing key and verify the signature before extraction. 2. Reject unsigned or invalidly signed archives by default. Do not rely on the directory name or manifest contents as proof of authenticity. 3. Use a strict manifest containing hashes, normalized relative paths, file types, and expected components. Verify every entry before copying it into the live workspace. 4. Present a component-level restoration summary and require separate confirmation before restoring Agent instructions, memory, scripts, or skills. 5. Restore into a staging directory first and scan instruction-bearing and executable content before activation. 6. Restrict archive entries to regular files and approved directories. Reject absolute paths, traversal components, hard links, symbolic links, device files, and unexpected file types. 7. Preserve an existing workspace backup so that poisoned state can be rolled back safely. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/migrate.sh:146
Finding
Backup Password Is Exposed Through OpenSSL Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/migrate.sh:146-157` and `scripts/migrate.sh:180-191` **Vulnerability Type**: Sensitive information exposure through command-line arguments **Risk Level**: Medium ### Vulnerable Code ```bash if $ENCRYPT; then echo "" if [ -n "${MIGRATE_PASSWORD:-}" ]; then PASS="$MIGRATE_PASSWORD" else echo -n " 🔑 Enter encryption password: " read -s PASS echo "" fi tar -czf - "$EXPORT_NAME" | openssl enc -aes-256-cbc -salt -pbkdf2 -pass "pass:$PASS" -out "$OUTPUT_DIR/${EXPORT_NAME}.tar.gz.enc" OUTPUT_FILE="$OUTPUT_DIR/${EXPORT_NAME}.tar.gz.enc" fi ``` The same pattern is used during restoration: ```bash if [ -n "${MIGRATE_PASSWORD:-}" ]; then PASS="$MIGRATE_PASSWORD" else echo -n " 🔑 Enter decryption password: " read -s PASS echo "" fi openssl enc -aes-256-cbc -d -salt -pbkdf2 -pass "pass:$PASS" -in "$BACKUP_FILE" | tar -xzf - -C "$TMPDIR" ``` ### Technical Analysis The `-pass "pass:$PASS"` form places the plaintext password in the OpenSSL process argument vector. Depending on operating-system process visibility and local monitoring configuration, command-line arguments may be exposed through process inspection tools, `/proc`, audit logs, diagnostic collection, or process telemetry. Reading the password without terminal echo protects it only during interactive entry. It does not protect the secret after it has been interpolated into OpenSSL's command line. The password also remains in the shell variable `PASS` after the cryptographic operation finishes. ### Attack Path 1. A user starts an encrypted export or restore operation. 2. The script launches OpenSSL with the plaintext password embedded in its command-line arguments. 3. A local process observer, monitoring agent, diagnostic collector, or other principal permitted to inspect the process arguments records the OpenSSL invocation. 4. The observer extracts the password from the `-pass pass:...` argument. 5. If the ...[truncated 617 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not use OpenSSL's `pass:` source for secrets. 2. Supply the password through a protected file descriptor, such as an anonymous pipe exposed through `/dev/fd`, using OpenSSL's `fd:` password source where supported. 3. Alternatively, use a temporary password file created with restrictive permissions, ensure it is never placed in a shared directory, and remove it reliably with a cleanup trap. 4. Prefer a backup tool or cryptographic format that securely prompts for credentials without exposing them in process arguments. 5. Clear secret variables immediately after use with `unset PASS MIGRATE_PASSWORD`. 6. Warn users against setting `MIGRATE_PASSWORD` in persistent shell configuration, command histories, service definitions, or other locations where environment secrets may be logged or exposed. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/migrate.sh:157
Finding
AES-CBC Backup Encryption Does Not Authenticate Archive Integrity<![CDATA[ ## Vulnerability Details **File Location**: `scripts/migrate.sh:157` and `scripts/migrate.sh:191` **Vulnerability Type**: Encryption without cryptographic authentication **Risk Level**: Medium ### Vulnerable Code ```bash tar -czf - "$EXPORT_NAME" | openssl enc -aes-256-cbc -salt -pbkdf2 -pass "pass:$PASS" -out "$OUTPUT_DIR/${EXPORT_NAME}.tar.gz.enc" ``` The corresponding decryption operation is: ```bash openssl enc -aes-256-cbc -d -salt -pbkdf2 -pass "pass:$PASS" -in "$BACKUP_FILE" | tar -xzf - -C "$TMPDIR" ``` ### Technical Analysis AES-256-CBC provides encryption but does not provide cryptographic authenticity or integrity by itself. PBKDF2 strengthens password-based key derivation, but it does not add message authentication. The script does not calculate or verify a MAC or digital signature over the encrypted archive. Consequently, it cannot reliably distinguish an authentic backup from an altered, corrupted, or substituted archive before passing decrypted output to `tar`. A successful extraction is not equivalent to cryptographic integrity verification. Targeted modification of compressed encrypted data may be unreliable, but complete archive substitution remains practical when an attacker knows the shared backup password or can convince the user to restore a separately constructed archive. ### Attack Path 1. A backup is transferred through or stored in a location that an attacker can modify. 2. The attacker corrupts the encrypted archive or, if the password is known, replaces it with a newly constructed malicious encrypted archive. 3. The user invokes the restore command and provides the expected password. 4. The script decrypts the archive without verifying a MAC or trusted signature. 5. If extraction succeeds, the unauthenticated contents proceed to the restore phase and may overwrite active Agent configuration and workspace state. ### Impact Assessment At minimum, unauthenticated encryption permits undetected corruption and denial ...[truncated 455 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use an authenticated encryption format that combines confidentiality and integrity. 2. If the selected OpenSSL interface cannot safely provide authenticated encryption for streamed archives, compute an encrypt-then-MAC construction with independently derived encryption and MAC keys. 3. Prefer a digital signature when backups must be authenticated as originating from a specific trusted machine or administrator. 4. Verify the MAC or signature over the complete archive before invoking `tar` or processing any archive-controlled data. 5. Store algorithm identifiers, format versions, KDF parameters, salt, nonce, and authentication data in a versioned backup envelope. 6. Treat authentication failure as fatal and ensure no partially extracted or restored files remain. 7. Update the documentation so that cloud-storage safety claims explicitly depend on authenticated integrity and secure password handling. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims full backup, encrypted safety, and one-command restore across machines, but the documented behavior is incomplete and asymmetric: some workspace content and memory are omitted, cron jobs are not restored, and restore may miss files. In a disaster-recovery or migration context, this can cause users to trust backups that are not actually complete, leading to data loss, broken restores, or false assurance about recoverability of sensitive operational state.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises and instructs shell execution (`bash scripts/migrate.sh ...`) but declares no explicit tool scope or permissions boundary. In a migration/backup skill, shell access can touch highly sensitive files like configs, memory, skills, and API-bearing auth profiles, so the absence of declared limits makes overbroad or unsafe execution more likely.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
When --no-encrypt is used, the script writes a plaintext archive of configs, memory, skills, and workspace data to disk with no strong warning that sensitive material may be exposed. Because this skill is specifically designed to collect an entire agent environment, the resulting archive is likely to contain secrets, private notes, or executable content and is high-value if copied or accessed by others.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The restore flow copies configuration and workspace content directly into the live OpenClaw directories without any confirmation, preview, or backup of existing files. In a migration skill that restores scripts and skills, this can unintentionally destroy local state or replace trusted files with older or malicious content from the archive.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [ -d "$RESTORE_DIR/config" ]; then
    echo "  → Restoring config"
    cp "$RESTORE_DIR/config/openclaw.json" "$OC_HOME/openclaw.json" 2>/dev/null && echo "    ✅ openclaw.json"
    chmod 600 "$OC_HOME/openclaw.json"
    if [ -d "$RESTORE_DIR/config/agents" ]; then
      cp -R "$RESTORE_DIR/config/agents/"* "$OC_HOME/agents/" 2>/dev/null && echo "    ✅ agents/"
      find "$OC_HOME/agents" -name "*.json" -exec chmod 600 {} \;
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [ -d "$RESTORE_DIR/config" ]; then
    echo "  → Restoring config"
    cp "$RESTORE_DIR/config/openclaw.json" "$OC_HOME/openclaw.json" 2>/dev/null && echo "    ✅ openclaw.json"
    chmod 600 "$OC_HOME/openclaw.json"
    if [ -d "$RESTORE_DIR/config/agents" ]; then
      cp -R "$RESTORE_DIR/config/agents/"* "$OC_HOME/agents/" 2>/dev/null && echo "    ✅ agents/"
      find "$OC_HOME/agents" -name "*.json" -exec chmod 600 {} \;
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.