Secret Vault on Aptos

First Flight #46
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Severity: medium
Valid

Architectural Inconsistency - Storage vs Access Pattern Mismatch

Architectural Inconsistency - Storage vs Access Pattern Mismatch

Description

  • The contract is designed to allow users to store their own secret vaults at their respective addresses through the set_secret() function

  • However, the get_secret() function only retrieves secrets from a hardcoded owner address, creating a fundamental mismatch between storage and retrieval operations

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 {});
}
#[view]
public fun get_secret (caller: address):String acquires Vault{
assert! (caller == @owner,NOT_OWNER);
let vault = borrow_global<Vault >(@owner);
vault.secret
}

Risk

Likelihood:

  • Every user who calls set_secret() will store their vault at their own address

  • Every call to get_secret() will fail for regular users since it only reads from the owner address

  • Only the hardcoded owner address can successfully retrieve secrets, but only if they also stored one

Impact:

  • Complete loss of functionality for all users except the hardcoded owner

  • User secrets become permanently inaccessible after storage

  • Broken contract logic renders the system unusable for its intended purpose

Proof of Concept

// User 0x123 stores a secret
set_secret(@0x123, b"my secret"); // Vault stored at 0x123
// User 0x123 tries to retrieve their secret
get_secret(@0x123); // FAILS: assertion error because 0x123 != @owner
// Only owner can retrieve, but from owner's address only
get_secret(@owner); // Only works if owner previously stored a secret

Recommended Mitigation

#[view]
- public fun get_secret (caller: address):String acquires Vault{
- assert! (caller == @owner,NOT_OWNER);
- let vault = borrow_global<Vault >(@owner);
+ public fun get_secret(caller: &signer): String acquires Vault {
+ let caller_address = signer::address_of(caller);
+ let vault = borrow_global<Vault>(caller_address);
vault.secret
}
Updates

Lead Judging Commences

bube Lead Judge 18 days ago
Submission Judgement Published
Validated
Assigned finding tags:

The protocol doesn't work as intended

Support

FAQs

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