T09 · Insecure Skill Coding Practices
- Location
skill.md:232- Finding
Wallet Private Key Persisted in Plaintext
- Content
View full analysis
Vulnerability Details
File Location:
skill.md, lines 232-235
Vulnerability Type: Plaintext storage of sensitive cryptographic material
Risk Level: HighVulnerable 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.hexas plaintext.Setting the file mode to
0600limits 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 aswallet.encand 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
- A user follows the onboarding example in
skill.md. - The workflow generates an EVM private key and writes it to
~/.campfire/secure/wallet_private_key.hex. - 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.
- The attacker copies the plaintext private key.
- The attacker imports the key into an EVM-compatible wallet or signing library.
- The attacker can generate signatures as the registered wallet and authoriz ...[truncated 1045 chars]
- A user follows the onboarding example in
- Remediation
View remediation
Remediation Suggestions
- Do not create a persistent plaintext private-key file.
- Store the key in an operating-system credential manager, hardware-backed keystore, HSM, cloud KMS, or equivalent protected secret store.
- 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.
- Generate and sign inside the protected storage boundary whenever supported, so application code never receives the raw private key.
- 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.
- 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.
- Create it in a private directory with mode
- Update the example to use the same encrypted
wallet.encstorage model required bywallet_guide.md. - 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.
