Back to skill

Security audit

OpenClaw Backup & Restore — Encrypted OpenClaw Snapshots

Security checks for vulnerabilities and agentic risk

Overview

This backup skill is mostly purpose-aligned, but it has unsafe backup, restore, credential, and setup behavior that could expose or delete local data if used as written.

Install only after review or fixes. Use a fine-grained GitHub token limited to one private backup repo, avoid running setup.py with sudo from an agent session, verify ~/openclaw-transport and ~/openclaw-transport-temp do not contain unrelated data, and treat restore as an operation that can overwrite local OpenClaw state. The credential handling and broad git staging should be fixed before routine use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/backup.py:137
Finding

Backup encryption password exposed through GPG process arguments

Content
View full analysis
Remediation
View remediation
`. - Create the pipe before launching GPG, write the password through the pipe, and close both ends on every success and error path. - Ensure the password is never included in exception messages, debug output, manifests, environment diagnostics, or logs. - Consider assigning a unique encryption secret to this repository and documenting a secure password-rotation procedure. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/config.py:82
Finding

Shell command injection in generated Git authentication helper

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/setup.py:60
Finding

Existing unrelated directory may be initialized and uploaded to GitHub

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/restore.py:198
Finding

Restore operation recursively deletes an unverified fixed directory

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (44)

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger text is overly broad and includes casual phrases like 'save my agent' and 'load my stuff on the new box,' which can cause the skill to activate in ambiguous contexts. Because this skill performs high-impact actions such as restore, deletion of older backups, and credential-dependent repo operations, accidental invocation materially increases the chance of destructive or privacy-impacting behavior.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

The chained command 'sudo apt-get update && sudo apt-get install -y ...' encourages a single-step privileged operation without an intermediate verification point. In agent-executed contexts, command chaining reduces opportunities for user review and error handling, making unintended root-level changes easier to carry out automatically.

Content

Scanner excerpt · SKILL.md (reported line 50)May include surrounding context.

md
Before running any command, verify:

1. **GPG is installed.** If not: `sudo apt-get update && sudo apt-get install -y gnupg gpg-agent`
2. **Credentials are configured** (see below)
3. **Setup has been run at least once** on this workspace: `python3 scripts/setup.py`

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · env-example.txt (reported line 2)May include surrounding context.

text
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · env-example.txt (reported line 3)May include surrounding context.

text
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/backup.py (reported line 26)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 5)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 6)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 9)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 10)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 26)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 45)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 47)May include surrounding context.

python
# OpenClaw Snapshot — Backup & Restore Configuration
# Copy this file to .env and fill in your values:
#   cp .env.example .env

# Strong passphrase used to encrypt/decrypt backups

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The example file explicitly instructs users to create a GitHub Personal Access Token with broad 'repo' scope for backup operations. Even though this is documentation rather than an embedded secret, requesting an overprivileged token increases the blast radius if the token is stolen, leaked from a local .env, or mishandled by the skill; in the context of a backup skill that pushes encrypted snapshots to GitHub, this is more dangerous because the token likely grants access to private repositories and backup history.

Content

Scanner excerpt · env-example.txt (reported line 8)May include surrounding context.

text
# Strong passphrase used to encrypt/decrypt backups
BACKUP_PASSWORD=

# GitHub Personal Access Token with 'repo' scope
# Create one at: https://github.com/settings/tokens
GITHUB_PAT=

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/backup.py (reported line 26)May include surrounding context.

python
# Skill root is the parent of the scripts/ directory
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"


def load_env_file() -> dict:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 22)May include surrounding context.

python
# Skill root is the parent of the scripts/ directory
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"


def load_env_file() -> dict:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 61)May include surrounding context.

python
# Skill root is the parent of the scripts/ directory
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"


def load_env_file() -> dict:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.py (reported line 90)May include surrounding context.

python
# Skill root is the parent of the scripts/ directory
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"


def load_env_file() -> dict:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/config.py (reported line 94)May include surrounding context.

python
askpass.close()
    os.chmod(askpass.name, stat.S_IRWXU)  # 700 — owner only

    env = os.environ.copy()
    env["GIT_ASKPASS"] = askpass.name
    env["GIT_TERMINAL_PROMPT"] = "0"  # never prompt interactively

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/backup.py (reported line 40)May include surrounding context.

python
for cmd in ["gpg", "gpg-agent"]:
        if shutil.which(cmd) is None:
            print(f"Error: {cmd} not found. Install with:")
            print("  sudo apt-get update && sudo apt-get install -y gnupg gpg-agent")
            sys.exit(1)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/restore.py (reported line 31)May include surrounding context.

python
for cmd in ["gpg", "gpg-agent"]:
        if shutil.which(cmd) is None:
            print(f"Error: {cmd} not found. Install with:")
            print("  sudo apt-get update && sudo apt-get install -y gnupg gpg-agent")
            sys.exit(1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises shell, file read/write, and environment-variable use but does not declare any explicit tool scope or permission boundaries. That creates an authorization gap where an agent may execute backup, restore, and setup flows with broad system access, including touching sensitive state in ~/.openclaw and using secrets from the environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description explains backup/restore mechanics but does not clearly warn that restore can overwrite the user's local agent state and that retention automatically deletes older backups beyond the last 10. In a stateful agent context, insufficient disclosure can lead to irreversible data loss or rollback to an unexpected state without informed user consent.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
90% confidence
Finding

The skill instructs use of 'sudo apt-get' to install packages, which elevates execution to root from within an agent-driven workflow. In this context, root-level package installation significantly expands impact if the skill is mis-triggered or the environment is not trusted, enabling system-wide modification beyond the intended backup task.

Content

Scanner excerpt · SKILL.md (reported line 50)May include surrounding context.

md
Before running any command, verify:

1. **GPG is installed.** If not: `sudo apt-get update && sudo apt-get install -y gnupg gpg-agent`
2. **Credentials are configured** (see below)
3. **Setup has been run at least once** on this workspace: `python3 scripts/setup.py`

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 132)May include surrounding context.

md
3. Present the version list to the user

### "Set up backups on this new workspace"
1. Confirm the user has a `.env` file with credentials (help them create one from `env-example.txt` if not)
2. Run `python3 <skill-path>/scripts/setup.py`

### "Restore a specific version"

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/backup.py (reported line 115)May include surrounding context.

python
# Pull latest from GitHub first (preserve backups from other workspaces)
    print("Syncing with GitHub...")
    subprocess.run(
        ["git", "-C", str(BACKUP_REPO), "pull", "origin", "main", "--quiet"],
        capture_output=True, env=env,
    )

Static analysis

No suspicious patterns detected.