musig: Reject empty pubkey list in GetMuSig2KeyAggCache
What changed, and why it matters
This commit fixes a small but real bug in Bitcoin Core's MuSig2 multi-signature helper. Previously, if someone asked the code to aggregate an empty list of public keys, it would pass an invalid empty list deeper into the cryptographic library, which could cause undefined behavior or a crash. The change now rejects an empty list immediately and returns a failure, and a test was added to make sure this stays fixed.
Treat as a low-severity hardening fix. Review whether any callers assume MuSig2AggregatePubkeys always succeeds, and consider backporting to maintained branches if the affected code is present. No immediate emergency response is warranted.
Security signals we found
Input validation added for empty cryptographic input list
Potential undefined behavior / crash in secp256k1_musig_pubkey_agg with empty input
New regression test for empty public key list
Fix is in a MuSig2/BIP 328 related code path
Evidence from the diff
In src/musig.cpp, GetMuSig2KeyAggCache() now checks if the input pubkeys vector is empty and returns false before calling secp256k1_musig_pubkey_agg(). Without this guard, an empty pubkey_ptrs vector would be passed to the secp256k1 function, likely resulting in an out-of-bounds read or undefined behavior. A regression test in src/test/bip328_tests.cpp verifies that MuSig2AggregatePubkeys({}) returns std::nullopt.
Changed components
src/musig.cppMuSig2AggregatePubkeysGetMuSig2KeyAggCacheBIP 328 testsInspect captured patch +10 / −0
diff --git a/src/musig.cpp b/src/musig.cpp
index 9a1b3442..af998085 100644
--- a/src/musig.cpp
+++ b/src/musig.cpp
@@ -18,6 +18,10 @@ constexpr uint256 MUSIG_CHAINCODE{
static bool GetMuSig2KeyAggCache(const std::vector<CPubKey>& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache)
{
+ if (pubkeys.empty()) {
+ return false;
+ }
+
// Parse the pubkeys
std::vector<secp256k1_pubkey> secp_pubkeys;
std::vector<const secp256k1_pubkey*> pubkey_ptrs;
diff --git a/src/test/bip328_tests.cpp b/src/test/bip328_tests.cpp
index 9fffa00b..630771d5 100644
--- a/src/test/bip328_tests.cpp
+++ b/src/test/bip328_tests.cpp
@@ -89,6 +89,12 @@ BOOST_AUTO_TEST_CASE(valid_keys)
}
}
+BOOST_AUTO_TEST_CASE(empty_pubkey_list)
+{
+ const std::optional<CPubKey> aggregate_pubkey{MuSig2AggregatePubkeys({})};
+ BOOST_CHECK(!aggregate_pubkey.has_value());
+}
+
BOOST_AUTO_TEST_CASE(invalid_key)
{
std::vector<std::string> test_vectors = {
Why this scored 37/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.