T09 · Insecure Skill Coding Practices
Error
- Location
- password_manager.py:12
- Finding
- Credentials Are Silently Stored in Plaintext When Encryption Is Unavailable<![CDATA[ ## Vulnerability Details **File Location**: `password_manager.py:12-18` and `password_manager.py:55-64` **Vulnerability Type**: Fail-open encryption handling resulting in plaintext credential storage **Risk Level**: High ### Vulnerable Code ```python try: from cryptography.fernet import Fernet ENCRYPTION_AVAILABLE = True except ImportError: ENCRYPTION_AVAILABLE = False print("警告: cryptography 未安装,密码将以明文存储") ``` ```python def encrypt_password(password: str) -> str: """加密密码""" if not ENCRYPTION_AVAILABLE: return password cipher = get_cipher() if cipher: return cipher.encrypt(password.encode()).decode() return password ``` ### Technical Analysis The application fails open when the `cryptography` dependency is unavailable. Instead of refusing to accept or persist credentials, `encrypt_password()` returns the original password unchanged. The caller then stores that value in `passwords.json` as though it were encrypted. A console warning is insufficient protection because users or automated agents may overlook it. This also contradicts the documented claim that passwords are encrypted at rest. The final `return password` creates an additional fail-open path if a cipher is unexpectedly unavailable. ### Attack Path 1. The application runs in an environment where `cryptography` is absent or cannot be imported. 2. `ENCRYPTION_AVAILABLE` is set to `False`. 3. A user or agent invokes the `add` or `import` command. 4. `encrypt_password()` returns the original credential without encryption. 5. `save_passwords()` writes the plaintext credential to `~/.openclaw/workspace/passwords.json`. 6. Any local user or process with read access to that file can recover the credential directly. ### Impact Assessment An attacker who can read the vault file can obtain every credential added while encryption was unavailable. The exposure includes passwords for all represented services and accounts and may consequently enab ...[truncated 146 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Fail closed if `cryptography` cannot be imported or cipher initialization fails. - Refuse all credential-writing operations until encryption is available and validated. - Remove every path that returns the original password from `encrypt_password()`. - Return a clear nonzero exit status with installation or recovery instructions. - Mark records with an explicit encryption format/version so plaintext cannot be mistaken for ciphertext. - Detect existing plaintext records and provide a controlled migration process that encrypts them before normal operation resumes. - Add tests verifying that no vault file is written when encryption initialization fails. ]]>
