T09 · Insecure Skill Coding Practices
Error
- Location
- skill.md:232
- Finding
- Wallet Private Key Persisted in Plaintext## Vulnerability Details **File Location**: `skill.md`, lines 232-235 **Vulnerability Type**: Plaintext storage of sensitive cryptographic material **Risk Level**: High ### Vulnerable Code ```python private_key_file = os.path.join(secure_dir, "wallet_private_key.hex") with open(private_key_file, "w", encoding="utf-8") as f: f.write(private_key) os.chmod(private_key_file, 0o600) ``` ### Technical Analysis The recommended onboarding workflow writes the newly generated EVM wallet private key directly to `~/.campfire/secure/wallet_private_key.hex` as plaintext. Setting the file mode to `0600` limits access to the owning operating-system account, but it does not encrypt the key at rest. Any malicious process operating under that account, compromised backup system, exposed disk snapshot, forensic reader, or later permission error can recover the complete private key without needing an additional secret. This implementation also conflicts with the project's own security guidance in `wallet_guide.md`, which recommends encrypted storage such as `wallet.enc` and states that private keys and API keys should be encrypted. The local access needed to store a wallet credential is relevant to the declared registration function, but retaining an unencrypted private key exceeds the minimum necessary exposure. Registration only requires creating a signature; it does not require permanent plaintext persistence. ### Attack Path 1. A user follows the onboarding example in `skill.md`. 2. The workflow generates an EVM private key and writes it to `~/.campfire/secure/wallet_private_key.hex`. 3. An attacker obtains read access through malware running as the user, a compromised home-directory backup, a disk snapshot, forensic access, or an accidental permission change. 4. The attacker copies the plaintext private key. 5. The attacker imports the key into an EVM-compatible wallet or signing library. 6. The attacker can generate signatures as the registered wallet and authoriz ...[truncated 1045 chars]
- Remediation
- ## Remediation Suggestions 1. Do not create a persistent plaintext private-key file. 2. Store the key in an operating-system credential manager, hardware-backed keystore, HSM, cloud KMS, or equivalent protected secret store. 3. If file-based storage is unavoidable, use a standard encrypted EVM keystore format with a strong user-supplied passphrase. Keep the passphrase outside the keystore file and outside source code, logs, command-line arguments, and environment dumps. 4. Generate and sign inside the protected storage boundary whenever supported, so application code never receives the raw private key. 5. If the wallet is needed only for registration, consider keeping it solely in memory, producing the registration signature, and discarding the key unless continued wallet ownership is an explicit requirement. 6. If temporary plaintext material is unavoidable: - Create it in a private directory with mode `0700`. - Create the file atomically with mode `0600`. - Exclude it from backups and synchronization services. - Remove it immediately after conversion to encrypted storage. - Avoid printing its path or contents in logs. 7. Update the example to use the same encrypted `wallet.enc` storage model required by `wallet_guide.md`. 8. Warn existing users to treat any wallet generated with the current example as potentially exposed, migrate relevant authority or assets to a new wallet, and securely remove residual plaintext copies and backups.
