Secret Vault on Aptos

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

The get_secret function takes an arbitrary address, allowing any user to read the owner's secret

The get_secret function takes an arbitrary address, allowing any user to read the owner's secret

Description

The secret_vault::get_secret function allows the caller of the function to read the secret stored in the owner's vault by passing the owner's address as the caller parameter. The function does not verify that the call is being made by the owner of the address being queried.

@> public fun get_secret (caller: address):String acquires Vault{
assert! (caller == @owner,NOT_OWNER);
let vault = borrow_global<Vault >(@owner);
vault.secret
}

Risk

Likelihood:

The likelihood is High because:

The owner's secret will be read by another user whenever they call secret_vault::get_secret while passing said owner's address as caller.

Impact:

The impact is High because:

The owner's secret stored in the vault is not secure, it can be easily read by anyone.

Proof of Concept

The following test demonstrates that any user can read the owner's secret:

#[test(owner = @0xcc, user = @0x123)]
fun test_anyone_can_read_owners_secret(owner: &signer, user: &signer) acquires Vault {
use aptos_framework::account;
// Set up test accounts
account::create_account_for_test(signer::address_of(owner));
account::create_account_for_test(signer::address_of(user));
// owner sets their secret
let secret = b"owner's secret";
set_secret(owner, secret);
// random caller reads owner's secret by passing owner's address
let owner_addr = signer::address_of(owner);
let leaked_secret = get_secret(owner_addr);
// Check that the user has successfully read the owner's secret
assert!(leaked_secret == string::utf8(secret), 1);
}

Recommended Mitigation

Restrict access to secrets by making get_secret an entry function that takes &signer and only allows the caller to access their own secret:

- public fun get_secret (caller: address):String acquires Vault{
- assert! (caller == @owner,NOT_OWNER);
- let vault = borrow_global<Vault >(@owner);
+ public entry fun get_secret(caller: &signer): String acquires Vault {
+ let addr = signer::address_of(caller);
+ let vault = borrow_global<Vault>(addr);
Updates

Lead Judging Commences

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

Lack of signer check in `get_secret`

Support

FAQs

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