Secret Vault on Aptos

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

Anyone can call set_secret

Root + Impact

Description

  • Normally, only the designated @owner account should be able to store a secret in the vault.

  • In the current implementation, any account can invoke set_secret and create a Vault resource under their own address, bypassing the intended ownership restriction.

This means that the system no longer enforces a single trusted authority. Instead of one protected secret controlled by the owner, multiple users can each publish a vault, which dilutes the access model and makes the application behave contrary to its specification.

public entry fun set_secret(caller:&signer,secret:vector<u8>){
let secret_vault = Vault{secret: string::utf8(secret)};
@> move_to(caller,secret_vault); // No ownership restriction
event::emit(SetNewSecret {});
}

Risk

Likelihood:

  • Any external account can directly call set_secret without restriction.

  • No validation exists on signer::address_of(caller), making exploitation trivial and guaranteed.

Impact:

  • Breaks the "single owner" design, multiple users can create their own vaults.

  • Reduces trust assumptions: the contract no longer enforces central ownership.

Proof of Concept

// Attacker signs a transaction with their own signer
let my_secret = b"hacked";
set_secret(attacker_signer, my_secret);
// Vault now exists under attacker's address, even though they are not @owner.

Recommended Mitigation

By asserting that signer::address_of(caller) equals @owner, only the authorized owner account can invoke set_secret. This enforces the intended model of a single trusted vault and prevents arbitrary users from creating unauthorized secrets.

- 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 {});
- }
+ public entry fun set_secret(caller:&signer, secret:vector<u8>) {
+ assert!(signer::address_of(caller) == @owner, NOT_OWNER);
+ let secret_vault = Vault{secret: string::utf8(secret)};
+ move_to(caller,secret_vault);
+ event::emit(SetNewSecret {});
+ }
Updates

Lead Judging Commences

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