Secret Vault on Aptos

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

Hardcoded @owner address breaks intended functionality

Description

  • The Secret Vault protocol is designed to allow users to store their private secrets securely, where only the vault creator (owner) should be able to set and retrieve their secret data.

  • The get_secret function contains a critical vulnerability where it uses a hardcoded @owner address for both access control validation and secret retrieval, completely breaking the intended per-user vault functionality and the actual owner will not be able to call get_secret with their address.

#[view]
public fun get_secret (caller: address):String acquires Vault{
assert! (caller == @owner, NOT_OWNER); // @> Hardcoded owner address check
let vault = borrow_global<Vault >(@owner); // @> Always retrieves from hardcoded @owner address
vault.secret
}

Risk

Likelihood:

  • Any user who creates a vault with an address different from the hardcoded @owner (0xcc in dev environment) will be unable to access their own vault, as the function will always fail the access control check

  • The hardcoded @owner address will be able to access any vault's secret data by calling get_secret with their own address, regardless of who actually created the vault

  • This vulnerability affects 100% of vault creations where the creator's address is not exactly the hardcoded @owner address

Impact:

  • Complete loss of access control - vault creators cannot retrieve their own secrets if their address differs from the hardcoded owner

  • Unauthorized access to sensitive data - the hardcoded owner can access any user's vault contents

  • Protocol functionality is fundamentally broken as it cannot support multiple independent users as intended

  • Users' private secrets (passwords, keys, sensitive information) are exposed to the hardcoded owner address

Proof of Concept

The following test will fail because the @owner is not the actual owner of the vault

module secret_vault::vault_test{
use std::signer;
use std::string::{Self, String};
use aptos_framework::event;
#[test_only]
use std::debug;
#[test(owner = @0xcc, user = @0x123, another_user = @0x456)]
fun test_hardcoded_owner_address_is_innefectual(owner: &signer, user: &signer, another_user: &signer) {
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));
account::create_account_for_test(signer::address_of(another_user));
// Create a new todo list for the user
let secret = b"i'm a secret";
secret_vault::vault::set_secret(another_user, secret);
// Get the owner address
let owner_address = signer::address_of(another_user);
assert!(secret_vault::vault::get_secret(owner_address) == string::utf8(secret), 4);
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);
+ let vault = borrow_global<Vault>(caller);
vault.secret
}

The fix removes the hardcoded owner address check entirely and instead retrieves the vault from the caller's address. This ensures that:

  1. Each user can only access their own vault

  2. The function works for any user who has created a vault

  3. Access control is properly enforced at the resource level (only the vault owner can call the function on their own vault)

Updates

Lead Judging Commences

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

The protocol doesn't work as intended

Appeal created

maroutis Auditor
15 days ago
bube Lead Judge
14 days ago
maroutis Auditor
14 days ago
bube Lead Judge 14 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.