https://github.com/DexlynLabs/bridge-repo/tree/6a772c126e0879928021156ca91b89ac4f1bfcae/move
In the announce function, any account can call the function and announce storage metadata for a validator without requiring the validator’s signature to be verified before storing the data.
public entry fun announce( account: &signer, validator: address, signature: vector<u8>, storage_location: String ) acquires ValidatorState { let validator_state = borrow_global_mut<ValidatorState>(@hp_validator);
// Ensure that the same storage metadata isn't being announced multiple times for the same validator. let replay_id = hash_concat( bcs::to_bytes(&validator), *string::bytes(&storage_location) ); assert!(!vector::contains(&validator_state.replay_protection, &replay_id), ERROR_ANNOUNCE_REPLAY); vector::push_back(&mut validator_state.replay_protection, replay_id);
// Verify that the signature matches the declared validator verify_validator_signed_announcement_internal( validator_state, validator, signature, storage_location );
// Store the announcement, Update storage locations if (!vector::contains(&validator_state.validators_list, &validator)) { vector::push_back(&mut validator_state.validators_list, validator); simple_map::add(&mut validator_state.storage_locations, validator, vector::empty<String>()); }; let locations = simple_map::borrow_mut<address, vector<String>>( &mut validator_state.storage_locations, &validator ); vector::push_back(locations, storage_location);
// emit events event::emit_event<AnnouncementEvent>( &mut validator_state.announcement_events, events::new_validator_announce_event( validator, storage_location ) ); }
The announce function is an entry function, meaning it can be called by any signer. However, it does not check whether account (the caller) is the validator. Instead, it allows any user to submit a validator’s storage location, relying only on verify_validator_signed_announcement_internal to check the signature.
Even though the signature is checked, it does not prevent unauthorized accounts from calling the function. An attacker could repeatedly attempt forged signatures and flood the contract with fake announcements.
Solution: Restrict Announcements to the Validator Modify the announce function to ensure that only the validator themselves can submit an announcement.
Fix: Add a Validator Check
public entry fun announce( account: &signer, validator: address, signature: vector<u8>, storage_location: String ) acquires ValidatorState { let validator_state = borrow_global_mut<ValidatorState>(@hp_validator);
// Ensure the caller is the validator assert!(signer::address_of(account) == validator, ERROR_INVALID_ACCOUNT);
// Ensure that the same storage metadata isn't being announced multiple times for the same validator. let replay_id = hash_concat( bcs::to_bytes(&validator), *string::bytes(&storage_location) ); assert!(!vector::contains(&validator_state.replay_protection, &replay_id), ERROR_ANNOUNCE_REPLAY); vector::push_back(&mut validator_state.replay_protection, replay_id);
// Verify that the signature matches the declared validator verify_validator_signed_announcement_internal( validator_state, validator, signature, storage_location );
// Store the announcement, Update storage locations if (!vector::contains(&validator_state.validators_list, &validator)) { vector::push_back(&mut validator_state.validators_list, validator); simple_map::add(&mut validator_state.storage_locations, validator, vector::empty<String>()); }; let locations = simple_map::borrow_mut<address, vector<String>>( &mut validator_state.storage_locations, &validator ); vector::push_back(locations, storage_location);
// emit events event::emit_event<AnnouncementEvent>( &mut validator_state.announcement_events, events::new_validator_announce_event( validator, storage_location ) ); } Why is this Fix Important? Prevents Unauthorized Announcements: Attackers can no longer submit announcements on behalf of a validator. Enhances Security with signer::address_of(account): Ensures the caller is the actual validator and not a random user. Reduces Potential DoS Attack Surface: Prevents spam submissions from unauthorized users.