Secret Vault on Aptos

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

Owner Cannot Retrieve Their Secret Due to Incorrect Access Control Logic

Root + Impact

Description

Normal Behavior

According to the documentation, the SecretVault should allow an owner to store a secret and later retrieve it, while preventing others from accessing it. So the owner should be set, and the owner should be able to call get_secret() without any reverts

Issue

The get_secret function contains multiple critical flaws that prevent it from working as documented:

  1. It references an undefined @owner address instead of using the caller's address

  2. It attempts to borrow the Vault resource from this undefined address rather than from the caller

  3. The owner check is incorrectly implemented, making it impossible for legitimate owner to access the secret stored

#[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: High

  • This issue will occur every time an owner attempts to retrieve their secret, making the core functionality completely broken.

  • The code as written cannot compile due to the undefined @owner address, so the contract is non-functional from inception.

Impact: High

  • The primary functionality of the contract (storing and retrieving secrets) is completely broken, rendering the application useless.

  • Impact 2

Proof of Concept

#[test(owner = @0x1, user = @0x123)]
fun test_owner_can_not_get_secret_vault(owner: &signer, user: &signer) acquires Vault{
use aptos_framework::account;
// Set up test environment
account::create_account_for_test(signer::address_of(owner));
account::create_account_for_test(signer::address_of(user));
// Create a new todo list for the user
let secret = b"i'm a secret";
set_secret(owner,secret);
get_secret(signer::address_of(owner));
debug::print(&b"All tests passed!");
}

Recommended Mitigation

#[view]
public fun get_secret(caller: address): String acquires Vault {
- assert!(caller == @owner, NOT_OWNER);
- let vault = borrow_global<Vault>(@owner);
+ // Get the secret from the caller's address - they can only access their own secret
+ let vault = borrow_global<Vault>(caller);
vault.secret
}
  • Removes the broken owner check

  • Uses the caller's address (owner) to retrieve the Vault resource

  • Maintains the security model where users can only access their own secrets, therefore only the owner can retrieve the secret they have set

Updates

Lead Judging Commences

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