Spark: Fix spend key buffer reuse - #1893
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/libspark/keys.cpp`:
- Around line 38-42: After the final s2.memberFromSeed call in the
key-derivation flow, explicitly cleanse both sensitive buffers, data and result,
before returning or allowing them to be destroyed. Use the existing project
zeroization utility and ensure cleansing occurs after the derived key has been
consumed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 58676a5f-435f-48a6-9641-d79201045b8a
📒 Files selected for processing (2)
src/libspark/keys.cppsrc/libspark/test/address_test.cpp
| std::string prefix2 = "s2_generation"; | ||
| hash256.Write(reinterpret_cast<const unsigned char*>(prefix2.c_str()), prefix2.size()); | ||
| hash256.Write(data.data(), data.size()); | ||
| hash256.Finalize(&result[0]); | ||
| this->s2.memberFromSeed(&result[0]); | ||
| hash256.Finalize(result.data()); | ||
| this->s2.memberFromSeed(result.data()); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Cleanse the final key-derivation buffers before returning.
After Line 36, data contains serialized s1. After Line 41, result contains the final hash output. The std::vector destructors release storage but do not guarantee zeroization. Sensitive intermediate data can remain in freed heap memory.
Add cleansing after the final memberFromSeed call.
Proposed fix
hash256.Finalize(result.data());
this->s2.memberFromSeed(result.data());
+ memory_cleanse(data.data(), data.size());
+ memory_cleanse(result.data(), result.size());
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| std::string prefix2 = "s2_generation"; | |
| hash256.Write(reinterpret_cast<const unsigned char*>(prefix2.c_str()), prefix2.size()); | |
| hash256.Write(data.data(), data.size()); | |
| hash256.Finalize(&result[0]); | |
| this->s2.memberFromSeed(&result[0]); | |
| hash256.Finalize(result.data()); | |
| this->s2.memberFromSeed(result.data()); | |
| std::string prefix2 = "s2_generation"; | |
| hash256.Write(reinterpret_cast<const unsigned char*>(prefix2.c_str()), prefix2.size()); | |
| hash256.Write(data.data(), data.size()); | |
| hash256.Finalize(result.data()); | |
| this->s2.memberFromSeed(result.data()); | |
| memory_cleanse(data.data(), data.size()); | |
| memory_cleanse(result.data(), result.size()); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/libspark/keys.cpp` around lines 38 - 42, After the final
s2.memberFromSeed call in the key-derivation flow, explicitly cleanse both
sensitive buffers, data and result, before returning or allowing them to be
destroyed. Use the existing project zeroization utility and ensure cleansing
occurs after the derived key has been consumed.
|
Do not review this. Has serious issues. |
|
Closing in favor of #1894. Keeping Generated by Claude Code |
PR intention
Prevent the Windows access violation observed after clicking Anonymize All.
Spark deterministic spend-key construction cleared its hash input and output vectors, then wrote through storage outside the vectors' live element ranges. This undefined behavior could corrupt memory and surface later in unrelated code, which explains the misleading
CNodeStatsandstd::stringframes in the reported stack trace.Code changes
memory_cleanseinstead of shrinking the vectors withclear().vector::data()only while the buffers contain live elements.s1ands2derivation from the same spend-key scalar.Testing
git diff --checkspark_address_tests/spend_key_recovery