Secret Vault on Aptos

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

Broken access control in get_secret

Root + Impact

Description

  • Normally, only the contract’s designated owner should be able to retrieve the secret.

  • The current implementation accepts a user-supplied caller address, which means anyone can pass @owner and satisfy the authorization check.

This results in a complete confidentiality failure, because the check depends on attacker-controlled input instead of a verified signer. Since the function is also marked #[view], attackers can exploit this at zero cost and retrieve the secret without leaving an on-chain trace.

#[view]
public fun get_secret(caller: address): String acquires Vault {
@> assert!(caller == @owner, NOT_OWNER); // User-controlled value
let vault = borrow_global<Vault>(@owner);
vault.secret
}

Risk

Likelihood:

  • Every call to get_secret is vulnerable, since the check relies entirely on user input.

  • The #[view] decorator exposes this function to anyone off-chain without transaction costs.

Impact:

  • Any attacker can read the owner’s secret by supplying @owner.

  • Complete loss of confidentiality of stored secrets.

Proof of Concept

// Attacker invokes the view function off-chain:
let leaked = get_secret(@owner);
// Returns the owner's private secret string

Recommended Mitigation

By requiring a &signer instead of an untrusted address, the function ensures that only the authenticated transaction signer is authorized. Using signer::address_of prevents spoofing, and cloning the string returns a safe copy of the stored secret. This closes the confidentiality leak.

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

Lead Judging Commences

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