Secret Vault

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

Missing Owner-Only Access Control on set_secret

Root + Impact

Description

  • Normal behavior: Only the designated Owner should be able to set the secret.
    Issue: set_secret lets any signer create a Vault under their own address. This contradicts the stated role model and enables anyone to create vaults arbitrarily, spamming storage and events and confusing off-chain consumers that assume a single “owner.”

// Move code, annotated
public entry fun set_secret(caller: &signer, secret: vector<u8>) {
let secret_vault = Vault{secret: string::utf8(secret)};
@> move_to(caller, secret_vault); // anyone can create their own Vault
event::emit(SetNewSecret {});
}

Risk

Likelihood:

  • Reason 1: Any account with a signer can call set_secret with no checks.
    Reason 2: Contract documentation explicitly restricts this to Owner, but code doesn’t, so integrators will rely on the wrong assumption and build unsafe UX on top.

Impact:

  • Impact 1: Breaks the Owner-only model; multiple unrelated vaults get created, diluting semantics.
    Impact 2: Enables cheap event and state spam at scale, increasing indexer load and confusing analytics.

Proof of Concept

// CLI: two different users create "owner-only" vaults, which should not be allowed by spec
aptos move run --function <mod>::vault::set_secret --args "vector<u8>:0x6869" --profile userA
aptos move run --function <mod>::vault::set_secret --args "vector<u8>:0x6869" --profile userB
// Both succeed; both emit SetNewSecret.

Recommended Mitigation

- public entry fun set_secret(caller:&signer, secret: vector<u8>) {
+ public entry fun set_secret(caller:&signer, secret: vector<u8>) acquires Vault {
+ assert!(signer::address_of(caller) == @owner, E_NOT_OWNER);
let secret_vault = Vault{secret: string::utf8(secret)};
- move_to(caller, secret_vault);
+ // write under @owner only
+ if (exists<Vault>(@owner)) {
+ let v = borrow_global_mut<Vault>(@owner);
+ v.secret = secret_vault.secret;
+ } else {
+ move_to(caller, secret_vault);
+ }
event::emit(SetNewSecret {});
}
Updates

Lead Judging Commences

bube Lead Judge 13 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
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.