T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/secure-storage.js:14
- Finding
- Universal Hardcoded Encryption Key Allows Offline Secret Recovery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/secure-storage.js:14-22` **Vulnerability Type**: Hardcoded cryptographic key material **Risk Level**: High ### Vulnerable Code ```javascript const SIMPLE_KEY = 'openclaw-secure-storage-v1'; function encrypt(text) { const iv = crypto.randomBytes(16); const key = crypto.scryptSync(SIMPLE_KEY, 'salt', 32); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); return iv.toString('hex') + ':' + encrypted; } ``` ### Technical Analysis The encryption key is deterministically derived from two constants distributed with the skill: - Password: `openclaw-secure-storage-v1` - Salt: `salt` Consequently, every installation derives the same AES-256 key. The random initialization vector prevents identical plaintext values from producing identical ciphertext, but it does not compensate for a publicly known encryption key. This also contradicts `SKILL.md:63`, which states that the encryption key is obtained from an environment variable. The implementation does not read any environment variable for key material. Anyone who obtains `secure-storage.json` can reproduce the `scryptSync` derivation and decrypt every stored value without interacting with the original system. ### Attack Path 1. The user stores API keys or other credentials with the skill. 2. The skill writes encrypted records to `$HOME/.openclaw/workspace/memory/secure-storage.json`. 3. An attacker obtains this file through a backup leak, accidental publication, compromised process, or access to the user's files. 4. The attacker downloads or reconstructs the publicly available skill code. 5. The attacker derives the AES key using the hardcoded password and salt. 6. For each record, the attacker parses the stored IV and ciphertext and decrypts the secret offline. 7. The recovered API keys or credentials are used against their corresponding exte ...[truncated 595 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove all hardcoded passwords, keys, and salts from the repository. 2. Obtain a high-entropy master key from an operating-system keychain, hardware-backed secret store, or managed KMS. 3. If environment-based configuration is required, reject execution when the key is absent rather than using a fallback. 4. If deriving a key from a user passphrase, generate a unique random salt per storage database and persist only that salt. 5. Use a memory-hard password derivation configuration with parameters selected for the deployment environment. 6. Provide a migration procedure that decrypts existing records and re-encrypts them under a unique protected key. 7. Rotate credentials previously stored with this version if the storage file may have been exposed. 8. Update `SKILL.md` so that its key-management and storage-path documentation matches the implementation. ]]>
