Category: Coding Mistakes
Multisig ISM allows duplicated signatures
High Severity
High Impact
High Likelihood
Description
Multisig ISM in the Hyperlane protocol is an Interchain Security module (ISM) that returns true when the signatures of m-of-n validators are provided, where the threshold and the list of validators are predetermined. It is implemented in merkleroot_multisig_ism.cairo and messageid_multisig_ism.cairo:
fn verify(self: @ContractState, _metadata: Bytes, _message: Message,) -> bool {
assert(_metadata.clone().size() > 0, Errors::EMPTY_METADATA);
let digest = self.digest(_metadata.clone(), _message.clone());
let (validators, threshold) = self.validators_and_threshold(_message);
assert(threshold > 0, Errors::NO_MULTISIG_THRESHOLD_FOR_MESSAGE);
let mut i = 0;
// for each couple (sig_s, sig_r) extracted from the metadata
loop {
if (i == threshold) {
break ();
}
let signature = self.get_signature_at(_metadata.clone(), i);
// we loop on the validators list public key in order to find a match
let mut cur_idx = 0;
let is_signer_in_list = loop {
if (cur_idx == validators.len()) {
break false;
}
let signer = *validators.at(cur_idx);
if bool_is_eth_signature_valid(digest, signature, signer) {
// we found a match
break true;
}
cur_idx += 1;
};
assert(is_signer_in_list, Errors::NO_MATCH_FOR_SIGNATURE);
i += 1;
};
true
}
However, this code allows a signature from one validator to be accepted more than once.
Impact
A malicious relayer who can obtain a signature of one validator can make the Multisig ISM return true by submitting the signature from one validator multiple times.
Recommendations
Consider ensuring that given signatures are not duplicated.
Remediation
This issue has been acknowledged by Pragma, and a fix was implemented in commit ac648a31↗.