T09 · Insecure Skill Coding Practices
- Location
scripts/backup.sh:35- Finding
Portable mode is ignored, allowing credentials to be included in plaintext backups
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real backup and restore skill, but its scripts can expose OpenClaw credentials through unsafe plaintext backup and restore handling, so it needs review before use.
Install only if you are comfortable with a backup tool that can read all OpenClaw data, store reusable secrets, schedule recurring jobs, and upload archives to configured cloud services. Before using it, keep encryption enabled, avoid portable/unencrypted full backups, protect all credential files with strict permissions, use least-privilege cloud identities, and restore only archives you trust.
scripts/backup.sh:35Portable mode is ignored, allowing credentials to be included in plaintext backups
scripts/backup.sh:60Complete plaintext archives are written to persistent storage before encryption
scripts/backup.sh:99Backup encryption passphrase is exposed through process command-line arguments
scripts/restore.sh:174Full restore extracts unvalidated archives directly into the user's home directory
references/setup-guide.md:97Cloud credential files lack consistent permission and ownership enforcement
references/destinations.md:3Setup instructions install mutable third-party packages without version or integrity pinning
The code is clearly a local backup script, not a full implementation of the broader declared description. It does support encrypted backups of ~/.openclaw and creates a workspace-only archive, which aligns with part of the description. However, the declared purpose explicitly includes restore, disaster recovery, migration, and storing backups to multiple cloud destinations, none of which are implemented in this supplied chunk. The gateway stop/start behavior is a reasonable supporting detail, not a mismatch. The main discrepancy is that the actual code only performs local backup creation and retention management, so the description overstates the capabilities of this code chunk.
Referenced artifact was not completely inspected
./scripts/restore.sh openclaw-myhost-20260215-full.tar.gz.gpg
Referenced artifact was not completely inspected
./scripts/restore.sh openclaw-myhost-20260215-full.tar.gz.gpg
Referenced artifact was not completely inspected
./scripts/restore.sh openclaw-myhost-20260215-full.tar.gz.gpg
Referenced artifact was not completely inspected
./scripts/restore.sh openclaw-myhost-20260215-full.tar.gz.gpg
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
if [[ -d "$WORKSPACE_DIR" ]]; then
SAFETY="${WORKSPACE_DIR}.pre-restore"
[[ -d "$SAFETY" ]] && rm -rf "$SAFETY"
log "Moving existing workspace → ${SAFETY}/"
mv "$WORKSPACE_DIR" "$SAFETY"
fi
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
if [[ -d "$WORKSPACE_DIR" ]]; then
SAFETY="${WORKSPACE_DIR}.pre-restore"
[[ -d "$SAFETY" ]] && rm -rf "$SAFETY"
log "Moving existing workspace → ${SAFETY}/"
mv "$WORKSPACE_DIR" "$SAFETY"
fi
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).
echo " 1. Review the restored files at ~/.openclaw/"
echo " 2. Start the gateway: openclaw gateway start"
echo " 3. If everything works, remove the safety copy:"
echo " rm -rf ~/.openclaw.pre-restore/"
fi
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).
echo " 1. Review the restored files at ~/.openclaw/"
echo " 2. Start the gateway: openclaw gateway start"
echo " 3. If everything works, remove the safety copy:"
echo " rm -rf ~/.openclaw.pre-restore/"
fi
The delete target is built from configuration-controlled bucket/path data and passed directly to aws s3 rm. If the configured bucket value includes an unexpected prefix/path, the cleanup step could delete an unintended remote object rather than only the just-uploaded test artifact.
safe_load_creds "$CRED_DIR/aws-credentials" || true
if aws s3 cp "$TEST_UPLOAD" "${BUCKET%/}/$TEST_NAME" --region "$REGION" 2>&1 && \
aws s3 rm "${BUCKET%/}/$TEST_NAME" --region "$REGION" 2>&1; then
pass "S3 upload + cleanup OK"
else
fail "S3 upload failed"; ((FAILURES++))
The R2 cleanup command constructs the deletion URI from configuration-controlled bucket data without enforcing that the field is bucket-only. A malformed or overbroad configured value could cause deletion of an unintended object in remote storage during cleanup.
safe_load_creds "$CRED_DIR/r2-credentials" || true
if aws s3 cp "$TEST_UPLOAD" "s3://${BUCKET}/$TEST_NAME" --endpoint-url "$ENDPOINT" 2>&1 && \
aws s3 rm "s3://${BUCKET}/$TEST_NAME" --endpoint-url "$ENDPOINT" 2>&1; then
pass "R2 upload + cleanup OK"
else
fail "R2 upload failed"; ((FAILURES++))
The GCS removal path is derived from the configured bucket string with only minimal trimming, so a bucket value containing additional path elements could broaden what object is targeted for deletion. In a backup tool that talks to real cloud storage, this increases the chance of accidental destructive operations against remote data.
gcloud auth activate-service-account --key-file="$CRED_DIR/gcs-key.json" 2>/dev/null || true
if gsutil cp "$TEST_UPLOAD" "${BUCKET%/}/$TEST_NAME" 2>&1 && \
gsutil rm "${BUCKET%/}/$TEST_NAME" 2>&1; then
pass "GCS upload + cleanup OK"
else
fail "GCS upload failed"; ((FAILURES++))
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.
## Manual Usage
### backup.sh — Create local backups
Every run produces **two files**:
The documentation is internally inconsistent about whether workspace backups are always encrypted: several sections say workspace backups are encrypted, while examples and filename conventions show plain .tar.gz restores. That ambiguity can lead operators to create, transfer, or restore unencrypted archives containing memory, notes, conversations, and other sensitive data, causing accidental disclosure.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
CLI needed: aws (AWS CLI)
pip install awscli
# or: sudo apt install awscli
Setup:
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
CLI needed: aws (AWS CLI)
pip install awscli
# or: sudo apt install awscli
Setup:
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
CLI needed: aws (AWS CLI)
pip install awscli
# or: sudo apt install awscli
Setup:
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.
**Setup:**
1. Create an S3 bucket in your AWS account
2. Create an IAM user with S3 write access (or use an existing one)
3. Save credentials to `~/.openclaw/credentials/backup/aws-credentials`:
```bash
The instructions tell users to place long-lived AWS credentials in a file under ~/.openclaw without any warning about file permissions, rotation, or the sensitivity of the secret material. In a backup skill, these credentials are especially valuable because they can grant persistent access to backup storage and may expose or enable tampering with protected data if the local machine or config directory is later compromised.
A downloaded GCS service account JSON key is a reusable bearer secret, and the instructions omit any warning that storing it locally creates a high-value target. In backup/restore context this is more dangerous because the key may allow broad object access to backup archives, enabling data theft or unauthorized modification depending on the account scope.
rclone.conf can contain reusable OAuth refresh tokens and remote definitions, but the instructions present copying it into ~/.openclaw as routine without warning about token sensitivity. In a backup destination skill, compromise of that config could grant ongoing access to cloud-stored backups and facilitate exfiltration of potentially sensitive archives.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
## Remote Retention & Lifecycle
Local backups are auto-pruned after 30 days (configurable). **Remote backups are never automatically deleted** — this is intentional. Storage is cheap, and offsite backups should be your safety net.
To manage remote retention, set lifecycle rules directly on your storage provider:
The guide explicitly instructs storing a backup encryption passphrase and provider credentials on disk under ~/.openclaw/credentials/backup, but it does not clearly warn the user that this creates a local secret-at-rest risk. In the context of a backup skill handling API keys and recovery secrets, compromised local access, malware, or overly broad filesystem permissions could expose both backup contents and cloud destinations.
The guide recommends cron-based unattended backups and optional chained cloud uploads, but does not clearly disclose that this will repeatedly collect local data and may automatically transmit it to third-party services. In a backup skill covering workspace contents and possibly credentials, lack of prominent consent and scope warning increases the risk of unintended ongoing data exfiltration or privacy exposure.
This script intentionally archives the entire ~/.openclaw directory, which likely includes credentials, tokens, and session material, then stores the backup on disk. While backup is the skill's stated purpose, persisting full application state materially increases exposure if the backup directory is accessed by another local user, synced insecurely, or encryption is disabled or mismanaged.
#!/usr/bin/env bash
# backup.sh — Create local backups of ~/.openclaw/
# Always produces two files:
# 1. Full backup (encrypted) — everything, for disaster recovery on same/similar environment
# 2. Workspace-only backup — just the workspace (memory, skills, files), safe for any environment