T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/cloud-backup.sh:741
- Finding
- Mandatory Encryption Can Be Bypassed for Secret-Bearing Backups<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cloud-backup.sh:741-755` and `scripts/cloud-backup.sh:1443-1451` **Vulnerability Type**: Plaintext exposure of sensitive backup data **Risk Level**: High ### Vulnerable Code ```bash decide_encryption() { # $1 mode; sets DO_ENCRYPT + enforces the secrets policy local required=false case "$1" in full) [ "$VERDICT" = "secret-material" ] && required=true ;; settings) required=true ;; # 100% secret material by construction workspace) ;; esac DO_ENCRYPT="$ENCRYPT" [ "$required" = "true" ] && DO_ENCRYPT=true if [ "$1" = "workspace" ] && [ "$NO_ENCRYPT" = "true" ] && [ "$required" != "true" ]; then DO_ENCRYPT=false fi if [ "$DO_ENCRYPT" = "true" ]; then if ! resolve_passphrase "$([ "$DRY_RUN" = "true" ] && echo soft)"; then if [ "$DRY_RUN" = "true" ]; then warn "${PASS_ERROR:-no passphrase configured} — a real run would FAIL (exit $E_PASSPHRASE)" elif [ "$required" = "true" ] && [ "$FORCE_PLAINTEXT" = "true" ] && [ -t 0 ]; then warn "FORCED PLAINTEXT for a secret-material scope (interactive --force-plaintext)" DO_ENCRYPT=false ``` The bypass is exposed through argument parsing: ```bash DRY_RUN=false; EVERYTHING=false; NO_UPLOAD=false; NO_ENCRYPT=false FORCE_PLAINTEXT=false; DEEP=false; ASSUME_YES=false; FORCE=false; IN_PLACE=false ... --force-plaintext) FORCE_PLAINTEXT=true ;; ``` ### Technical Analysis The Skill documentation states that sensitive `full` and `settings` backups force encryption and that plaintext output must be rejected. The implementation contradicts that policy in two ways: 1. An interactive invocation with `--force-plaintext` explicitly changes `DO_ENCRYPT` to `false` after the script has determined that the archive contains secret material. 2. For `full` mode, encryption is considered mandatory only when the heuristic verdict is exactly `secret-material`. If `config.encrypt=false` and the heuristic returns ...[truncated 2328 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the `--force-plaintext` option and all `FORCE_PLAINTEXT` handling. 2. Make encryption unconditional for `full` and `settings` modes: ```bash case "$1" in full|settings) required=true ;; workspace) required=false ;; esac ``` 3. Reject `config.encrypt=false` for `full` and `settings`, regardless of the heuristic verdict. 4. Permit plaintext output only for an explicitly requested `workspace --no-encrypt` operation. 5. Treat the sensitivity verdict as additional diagnostic information rather than the only enforcement boundary. 6. Add regression tests proving that: - `backup full` cannot create plaintext output; - `backup settings` cannot create plaintext output; - no command-line flag can bypass mandatory encryption; - `config.encrypt=false` is rejected for sensitive modes; - only `workspace --no-encrypt` can intentionally produce plaintext. 7. Remove `--force-plaintext` from usage text and document that sensitive-mode encryption has no override. ]]>
