T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/cloud-backup.sh:747
- Finding
- Encryption Policy Bypass Allows Plaintext Secret-Bearing Backups<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cloud-backup.sh:747-750` **Vulnerability Type**: Encryption policy bypass resulting in plaintext sensitive-data storage **Risk Level**: High ### Vulnerable Code ```bash elif [ "$required" = "true" ] && [ "$FORCE_PLAINTEXT" = "true" ] && [ -t 0 ]; then warn "FORCED PLAINTEXT for a secret-material scope (interactive --force-plaintext)" DO_ENCRYPT=false else ``` ### Technical Analysis The script determines that `full` and `settings` backups require encryption when they contain credentials, secret stores, configuration secrets, or other sensitive OpenClaw state. However, when no usable passphrase is available, the `--force-plaintext` option overrides this requirement if standard input is attached to a terminal. Setting `DO_ENCRYPT=false` causes the plaintext archive to continue through the normal backup pipeline. Depending on configuration, it can be published to the local archive directory and uploaded to the configured S3-compatible destination. This behavior contradicts the documented security contract in `SKILL.md`, which states that secret-bearing scopes force encryption and that the script refuses to produce plaintext archives for those scopes. Merely requiring a TTY does not provide meaningful authorization or prevent an operator, automation wrapper with a pseudo-terminal, or misdirected agent invocation from using the bypass. ### Attack Path 1. OpenClaw state contains sensitive material, such as `credentials/`, secret-store files, authentication profiles, or plaintext secrets in `openclaw.json`. 2. No valid GPG passphrase is configured or the configured passphrase cannot be resolved. 3. The script is invoked from a terminal with: ```bash bash scripts/cloud-backup.sh backup full --force-plaintext ``` or: ```bash bash scripts/cloud-backup.sh backup settings --force-plaintext ``` 4. Sensitivity detection marks encryption as required. 5. The override branch sets `DO_E ...[truncated 789 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the `--force-plaintext` override for all secret-bearing scopes. 2. When `required=true`, fail unconditionally unless a valid encryption passphrase has been resolved. 3. Permit plaintext output only for scopes explicitly designed to be non-sensitive, such as a workspace-only backup that has passed sensitivity checks. 4. If users need a shareable archive, require `config.excludeSecrets=true` and verify that the resulting sensitivity verdict is `refs-only` before allowing encryption to be disabled. 5. Remove `--force-plaintext` from argument parsing and usage text to prevent accidental or undocumented invocation. 6. Add regression tests confirming that `full` and `settings` backups cannot produce or upload `.tar.gz` plaintext artifacts under any combination of TTY state, flags, or missing passphrase conditions. 7. Ensure failed encryption-policy checks clean the staging directory without publishing or uploading any plaintext artifact. ]]>
