Secret Vault on Aptos

First Flight #46
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Secret_vault - Missing Access Control in set_secret() Allows Any Account to Override Secrets

Description

The set_secret() function in the SecretVault module lacks proper access control validation, allowing any account to set or override secrets. While the contract documentation explicitly states that "Only the owner should be able to store a secret and then retrieve it later", the implementation permits any caller to invoke this function and store secrets under their own account, violating the intended security model.

Root Cause

The function accepts any &signer without validating that the caller is the authorized owner (@owner). The function is designed to be called only by the contract owner, but no access control mechanism is implemented to enforce this restriction, allowing any account to invoke it.

public fun set_secret(caller:&signer,secret:vector<u8>){
// @audit-issue the function is public we need an assert to verifiy the signer
// otherwise an other account can set the secret
let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
event::emit(SetNewSecret {});
}

Key issues:

  1. No validation that caller is the contract owner (@owner)

  2. Any account can call set_secret() and store secrets under their own address

  3. Multiple accounts can have their own vault resources, breaking the intended single-vault design

Risk

Likelihood: High - Any account can trivially call this public function without restrictions

Impact: High - Complete bypass of the intended access control model, allowing unauthorized secret storage

Impact

High severity because:

  • Breaks the fundamental security assumption that only the owner can manage secrets

  • Violates the Move ownership model by allowing unauthorized resource storage

Proof of Concept

The following test demonstrates how any attacker account can successfully set secrets without being the owner:

module attacker::Attacker {
use secret_vault::vault;
fun attacker_set_secret(account: signer){
vault::set_secret(&account, b"new secret");
}
#[test(account = @attacker)]
fun test_attack(account: signer){
attacker_set_secret(account);
}
}
BUILDING aptos-secret-vault
Running Move unit tests
[debug] 0x416c6c2074657374732070617373656421
[ PASS ] 0xa77ac4::Attacker::test_attack
[ PASS ] 0x234::vault::test_secret_vault
Test result: OK. Total tests: 3; passed: 3; failed: 0
{
"Result": "Success"
}

Recommended Mitigation

Implement access control by adding an assertion to verify the caller is the authorized owner:

public fun set_secret(caller:&signer,secret:vector<u8>){
+ assert!(signer::address_of(caller) == @owner, NOT_OWNER);
let secret_vault = Vault{secret: string::utf8(secret)};
move_to(caller,secret_vault);
event::emit(SetNewSecret {});
}

Test Results After Mitigation:

BUILDING aptos-secret-vault
Running Move unit tests
[ FAIL ] 0xa77ac4::Attacker::test_attack # Attacker rightfully fails
[ PASS ] 0x234::vault::test_secret_vault

This fix ensures that only the designated owner (@owner) can invoke the set_secret() function, properly enforcing access control and maintaining the security guarantees of the vault system. The @owner address must be specified during deployment.

Updates

Lead Judging Commences

bube Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Anyone can call `set_secret` function

In Move for Aptos, the term "owner" refers to a signer, which is a verified account that owns a given resource, has permission to add resources and the ability to grant access or modify digital assets. Following this logic in this contest, the owner is the account that owns `Vault`. This means that anyone has right to call `set_secret` and then to own the `Vault` and to retrieve the secret from the `Vault` in `get_secret` function. Therefore, this group is invalid, because the expected behavior is anyone to call the `set_secret` function.

Support

FAQs

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

Give us feedback!