Secret Vault on Aptos

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

Missing Access Control in `set_secret` Function Allows Any User to Create Vaults

Root + Impact

Missing Access Control in set_secret Function which creates Critical Impact

Description

  • The normal behavior should require that only the designated owner can store secrets in their vault, ensuring exclusive control over sensitive data.

  • The current implementation allows any user to call set_secret and create a vault under their own account, completely bypassing the intended owner-only access control mechanism.

// Root cause in the codebase with @> marks to highlight the relevant section
public entry fun set_secret(caller:&signer,secret:vector<u8>){
@> let secret_vault = Vault{secret: string::utf8(secret)};
@> move_to(caller,secret_vault); // No owner verification - any signer can create vault
event::emit(SetNewSecret {});
}

Risk

Likelihood:

  • Any user can call this function since it's a public entry function with no access control checks

  • Attackers can immediately exploit this by calling the function with any signer account

Impact:

  • Complete bypass of the owner-only security model, allowing unauthorized secret storage

  • Potential for attackers to create confusing vault states across multiple accounts

  • Violation of the core security requirement that only the owner should manage secrets

Proof of Concept

#[test(attacker = @0x999)]
fun test_unauthorized_vault_creation(attacker: &signer) {
use aptos_framework::account;
// Create account for attacker
account::create_account_for_test(signer::address_of(attacker));
// Attacker can successfully create their own vault - THIS SHOULD FAIL
set_secret(attacker, b"unauthorized_secret");
// Verify the attacker now has a vault (security violation)
assert!(exists<Vault>(signer::address_of(attacker)), 1);
}

Explanation: This test demonstrates that any user (represented by attacker with address @0x999) can successfully call set_secret and create their own vault. The test passes, proving the vulnerability exists. In a secure implementation, this call should fail with an access control error since the attacker is not the designated owner.

Recommended Mitigation

+ const OWNER_ADDRESS: address = @secret_vault;
+ const E_NOT_OWNER: u64 = 1;
public entry fun set_secret(caller:&signer,secret:vector<u8>){
+ let caller_address = signer::address_of(caller);
+ assert!(caller_address == OWNER_ADDRESS, E_NOT_OWNER);
let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
event::emit(SetNewSecret {});
}

Explanation: The mitigation adds proper access control by defining a constant OWNER_ADDRESS and checking that only this address can call the function. The assert! statement will abort execution with error code E_NOT_OWNER if any unauthorized user attempts to set a secret, preventing the security bypass.

Updates

Lead Judging Commences

bube Lead Judge 15 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.