feat(wallet): wrap secret_key_hex() in SecretString to prevent accidental key leaks#765
Conversation
secret_key_hex() now returns reliakit_secret::SecretString instead of a plain String. Debug and Display on SecretString print [REDACTED], so the private key cannot leak through tracing macros, error messages, or accidental println!. Call sites that legitimately need the value call .expose_str() explicitly — making exposure visible in the code. CLI commands (wallet generate/decrypt, genesis-wallets) use expose_str() because the operator explicitly requested their private key. Keystore encrypt/decrypt and tests use expose_str() at the one point they need the raw hex for AES-GCM input or round-trip assertions. Dependency: reliakit-secret 0.1 (MIT, published to crates.io). cargo check -D warnings: clean. 22 sentrix-wallet tests: all pass.
|
Warning Review limit reached
More reviews will be available in 21 minutes and 7 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Wallet::secret_key_hex()previously returned a plainString. That type prints freely throughDebug,Display,tracingmacros, andserde_json::json!— a single misplacedtracing::info!("{:?}", wallet)or a future#[derive(Debug)]on a struct holdingWalletwould silently log the raw private key hex.secret_key_hex()now returnsreliakit_secret::SecretString(from the founder's own reliakit crate, MIT, published to crates.io).DebugprintsSecret([REDACTED]),Displayprints[REDACTED]. The actual hex is only accessible via.expose_str(), which makes every exposure explicit and greppable.Call site changes
keystore.rs:73(encrypt)wallet.secret_key_hex()→.expose_str()forhex::decodeinputkeystore.rstests.expose_str()for comparisons andhex::decodeinputswallet.rstests.expose_str()for length/char checks, comparisons,from_private_keyinputcommands/wallet.rs(x2).expose_str()— operator explicitly requested their key via CLIcommands/misc.rs(x2).expose_str()— genesis wallet generation, operator-initiatedWhat this doesn't fix
Memory zeroization of the
SecretStringheap allocation — reliakit-secret is a log-leak guard, not a zeroize library. TheZeroizing<[u8;32]>onsecret_key_bytesalready handles the source bytes. TheSecretStringreturned bysecret_key_hex()is a transient copy; callers that need to zero it explicitly can call.into_inner()andzeroize().Test plan
cargo check --workspace -D warningscleansentrix-wallettests pass (including all keystore encrypt/decrypt/migrate round-trips)