T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/backup.sh:35
- Finding
- Portable mode is ignored, allowing credentials to be included in plaintext backups<![CDATA[ ## Vulnerability Details **File Location**: `scripts/backup.sh:35-39, 92-110`; related documentation at `references/setup-guide.md:31-45` **Vulnerability Type**: Configuration enforcement failure and plaintext sensitive-data exposure **Risk Level**: High ### Vulnerable Code ```bash ENCRYPT="${BACKUP_ENCRYPT:-$(read_config encrypt)}" ENCRYPT="${ENCRYPT:-true}" RETAIN_DAYS="${BACKUP_RETAIN_DAYS:-$(read_config retainDays)}" RETAIN_DAYS="${RETAIN_DAYS:-30}" ``` ```bash # --------------------------------------------------------------------------- # 1. Full backup (encrypted) # --------------------------------------------------------------------------- FULL_NAME="openclaw-${HOSTNAME_SHORT}-${TIMESTAMP}-full.tar.gz" FULL_PATH="$BACKUP_DIR/$FULL_NAME" log "Creating full backup..." tar czf "$FULL_PATH" -C "$HOME" .openclaw/ log "Full archive: $FULL_PATH ($(du -h "$FULL_PATH" | cut -f1))" if [[ "$ENCRYPT" == "true" ]]; then log "Encrypting full backup with AES-256..." gpg --batch --yes --symmetric --cipher-algo AES256 \ --passphrase "$PASSPHRASE" \ --output "${FULL_PATH}.gpg" \ "$FULL_PATH" rm -f "$FULL_PATH" FULL_PATH="${FULL_PATH}.gpg" log "Encrypted: $FULL_PATH ($(du -h "$FULL_PATH" | cut -f1))" else log "WARNING: Full backup is NOT encrypted — contains credentials in plaintext" fi ``` The documented setup directs portable-mode users to configure: ```text If they choose portable/unencrypted, set `encrypt: false` and `mode: "portable"` in config. ``` ### Technical Analysis The backup implementation reads the `encrypt` and `retainDays` settings, but never reads or enforces the documented `mode` setting. It unconditionally archives the complete `~/.openclaw/` directory, including `~/.openclaw/credentials/`. Consequently, selecting the documented portable mode does not exclude credentials. If portable mode is combined with `encrypt: false`, the script creates an unencrypted full archive containing API keys, cloud credentials, to ...[truncated 1034 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Read and validate the `mode` setting before constructing an archive. - In portable mode, archive an explicit allowlist of portable paths rather than using broad exclusions. - Explicitly exclude `~/.openclaw/credentials/`, session secrets, tokens, and other machine-specific state. - Reject unsupported or missing mode values instead of silently falling back. - Enforce the invariant that a full backup cannot run when encryption is disabled. - Add automated tests that inspect archive contents and verify that portable backups never contain credentials. - Update documentation to match the implementation and remove claims that are not programmatically enforced. ]]>
