set_secret() only publishes the secret with move_to() + set_secret() can only be called once.
Description
-
set_secret() should be able to be called multiple times. For example when the owner wants to change their secret.
-
set_secret() only publishes the secret with move_to(). It does not handle the case when the Vault resource exists already for the owner
public entry fun set_secret(caller:&signer,secret:vector<u8>){
let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
@> event::emit(SetNewSecret {});
}
Risk
Likelihood:
Impact:
Proof of Concept
#[test(owner = @0xcc, user = @0x123)]
#[expected_failure()]
fun test_set_secret_multiple_failure(owner: &signer, user: &signer) {
use aptos_framework::account;
account::create_account_for_test(signer::address_of(owner));
account::create_account_for_test(signer::address_of(user));
let owner_secret_00 = b"owner secret 00";
set_secret(owner, owner_secret_00);
let owner_secret_01 = b"owner secret 01";
set_secret(owner, owner_secret_01);
}
Run with
aptos move test --filter test_set_secret_multiple_failure
Output
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING aptos-secret-vault
Running Move unit tests
[ PASS ] 0x234::vault::test_set_secret_multiple_failure
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
"Result": "Success"
}
Recommended Mitigation
Add an update handler for the use case when the Vault resource already exists in the owners account.
- public entry fun set_secret(caller:&signer,secret:vector<u8>){
+ public entry fun set_secret(caller:&signer,secret:vector<u8>) acquires Vault {
+ let caller_address = signer::address_of(caller);
+ assert! (caller_address == @owner,NOT_OWNER);
+ if (exists<Vault>(caller_address)) {
+ // Vault already exists, perform upddate
+ let vault = borrow_global_mut<Vault>(caller_address);
+ vault.secret = string::utf8(secret);
+ } else {
+ // first publish
let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
+ };
event::emit(SetNewSecret {});
}