Secret Vault on Aptos

First Flight #46
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Lack of ownership control in `set_secret`

Summary

The set_secret function lacks proper access control, allowing anyone (not just the owner) to set vault secrets. This enables unlimited users to call set_secret and create arbitrary Vault entries to their own addresses, leading to unbounded and potentially polluted global storage.

Description

The set_secret function has no access control in which anyone allows to set the vault secret instead of being exclusive to only owner.

public entry fun set_secret(caller:&signer,secret:vector<u8>){
// no access control found!
<@@>! let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
event::emit(SetNewSecret {});
}

Risk

Likelihood:

  • This occurs every time any user calls set_secret.

Impact:

  • Unlimited number of users can call set_secret and write Vault to their own addresses, polluting global storage.

Proof of Concept

Add the following test in secret_vault.move:

#[test(owner = @0xcc, random_user = @0x123)]
fun test_anyone_can_call_set_secret(owner: &signer, random_user: &signer) acquires Vault{
use aptos_framework::account;
// Set up caller test environment
account::create_account_for_test(signer::address_of(owner));
account::create_account_for_test(signer::address_of(random_user));
// Owner set vault secret
let owner_secret = b"chocolate";
set_secret(owner, owner_secret);
// Random user set vault secret
let random_secret = b"pancake";
set_secret(random_user, random_secret);
let owner_add = signer::address_of(owner);
let owner_vault = borrow_global<Vault>(owner_add);
let random_user_add = signer::address_of(random_user);
let random_user_vault = borrow_global<Vault>(random_user_add);
// check if random user's secret is successfully stored in Vault besides owner's secret
assert!(owner_vault.secret == string::utf8(owner_secret), 3);
assert!(random_user_vault.secret == string::utf8(random_secret), 4);
}

In terminal run aptos move test -f test_anyone_can_call_set_secret:

$ aptos move test -f test_anyone_can_call_set_secret [11:14:02]
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING aptos-secret-vault
Running Move unit tests
[ PASS ] 0x234::vault::test_anyone_can_call_set_secret
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
"Result": "Success"
}

The test passed indicating that any random user can successfully set a secret to the contract's global storage Vault by calling set_secret function.

Recommended Mitigation

Implement access control in set_secret function

public entry fun set_secret(caller:&signer,secret:vector<u8>) acquires Vault{
+ let caller_add = signer::address_of(caller);
+ assert!(caller_add == @owner, NOT_OWNER);
...
}
Updates

Lead Judging Commences

bube Lead Judge 16 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Anyone can call `set_secret` function

In Move for Aptos, the term "owner" refers to a signer, which is a verified account that owns a given resource, has permission to add resources and the ability to grant access or modify digital assets. Following this logic in this contest, the owner is the account that owns `Vault`. This means that anyone has right to call `set_secret` and then to own the `Vault` and to retrieve the secret from the `Vault` in `get_secret` function. Therefore, this group is invalid, because the expected behavior is anyone to call the `set_secret` function.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.