T09 · Insecure Skill Coding Practices
- Location
scripts/wallet_manager.py:30- Finding
Plaintext Private-Key Exposure Through Serialization and Console Output
- Content
View full analysis
Vulnerability Details
File Location:
scripts/wallet_manager.py:30-34
Additional Locations:README.md:27-32,scripts/wallet_manager.py:94-98,examples/basic_usage.py:20-24
Vulnerability Type: Plaintext handling and disclosure of wallet private keys
Risk Level: HighVulnerable Code
scripts/wallet_manager.py:30-34:python def to_dict(self) -> Dict: return { "address": self.address, "private_key": self.private_key }README.md:27-32:python # Create a new wallet wallet = WalletManager.create_wallet() print(f"Address: {wallet.address}") print(f"Private Key: {wallet.private_key}") # Query balancescripts/wallet_manager.py:94-98:python wallet = WalletManager.create_wallet() print(f"Address: {wallet.address}") print(f"Private Key: {wallet.private_key[:20]}...{wallet.private_key[-10:]}") # Validate addressexamples/basic_usage.py:20-24:python print("\n[Step 1] Creating a new Ethereum wallet...") wallet = WalletManager.create_wallet() print(f"✓ Address: {wallet.address}") print(f"✓ Private Key: {wallet.private_key[:20]}...{wallet.private_key[-10:]}") print(" ⚠️ IMPORTANT: Save this private key securely!")Technical Analysis
Wallet.to_dict()places the complete private key into a normal dictionary without encryption, access controls, or an explicit secret-export operation. Such dictionaries can easily be serialized, logged, sent through telemetry, included in exception diagnostics, or persisted in plaintext.The documented quick-start example is more severe because it explicitly prints the complete private key. The executable examples also print private-key fragments. Although those fragments alone do not expose the entire key, they unnecessarily disclose secret material and encourage unsafe handling practices.
Private keys are bearer credentials: possession of the full key is su ...[truncated 1452 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove
private_keyfrom the defaultto_dict()output. Default serialization should contain only non-secret wallet metadata such as the public address. - Replace generic plaintext export with an explicitly named operation such as
export_encrypted_keystore(password). - Use the Ethereum encrypted keystore format and a strong, user-supplied password with an appropriate key-derivation function.
- If encrypted keystores are written to disk, create files with restrictive owner-only permissions and avoid predictable temporary files.
- Remove all complete and partial private-key output from the README, examples, tests, and command-line demonstrations.
- Ensure object representations, logs, exceptions, telemetry, and debugging output redact secret values.
- Add tests that verify private keys are absent from default serialization and console output.
- Document secure backup procedures and advise users to rotate any wallet whose key may already have entered logs or plaintext storage.
- Remove
