Root + Impact
Description
Only the designated owner (@owner address from Move.toml) should be able to store a secret in the Vault resource. Other accounts should have no ability to modify the owner’s stored secret.
 
Issue:
set_secret does not verify that the caller is the owner. This allows any account to call set_secret and overwrite the Vault resource belonging to the owner. In Move, move_to will replace the existing resource if one exists for that account, so this directly destroys the original secret.
public entry fun set_secret(caller:&signer, secret:vector<u8>) {
    let secret_vault = Vault{secret: string::utf8(secret)};
    // @> No ownership check here
    move_to(caller, secret_vault);
    event::emit(SetNewSecret {});
}
Risk
Likelihood:
- 
Any user can call set_secretwithout restriction.
 
- 
This will occur immediately when a malicious actor sees the module on-chain, since the entry function is public and permissionless. 
Impact:
- 
Permanent loss of the original secret stored by the owner. 
- 
Integrity breach: malicious data is stored in place of the true secret, breaking application trust. 
Proof of Concept:
Test case:
#[test(owner = @0xcc, attacker = @0x999)]
fun test_overwrite_secret(owner: &signer, attacker: &signer) acquires Vault {
    use aptos_framework::account;
    // Create accounts for both the legitimate owner and an attacker
    account::create_account_for_test(signer::address_of(owner));
    account::create_account_for_test(signer::address_of(attacker));
    // STEP 1: Owner stores their legitimate secret
    let original_secret = b"legit secret";
    set_secret(owner, original_secret);
    // At this point, Vault is stored under @0xcc (the owner’s address)
    // STEP 2: Attacker creates their *own* Vault
    // PROBLEM: set_secret() uses the caller's signer address and does not check if they are the `owner`
    let malicious_secret = b"hacked secret";
    set_secret(attacker, malicious_secret);
    // This creates a *separate* Vault resource at @0x999 (attacker’s address)
    // STEP 3: Attacker retrieves their own Vault
    let vault = borrow_global<Vault>(signer::address_of(attacker));
    // STEP 4: This passes — attacker’s Vault contains their malicious secret
    assert!(vault.secret == string::utf8(malicious_secret), 1000);
    // 💡 Issue demonstrated:
    // Any account can call set_secret() to store *their own* Vault.
    // The spec requires that only the single `owner` address should be able to store a secret.
    // This is a logical flaw — there’s no global ownership check in set_secret().
}
 
 
Test Results:
Auditing/FirstFlight/2025-07-secret-vault\$ aptos move test --filter test\_overwrite\_secret
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING aptos-secret-vault
Running Move unit tests
\[ PASS ] 0x234::vault::test\_overwrite\_secret
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
"Result": "Success"
}
Recommended Mitigation:
Give permisson only to the owner and restrict to others...
 public entry fun set_secret(caller:&signer, secret:vector<u8>) {
- Not checking any Owner this cause protocol (mentioned in the docs(.md))
     let secret_vault = Vault{secret: string::utf8(secret)};
     move_to(caller, secret_vault);
     event::emit(SetNewSecret {});
 }
After add the assert u can restrict the permission and give permission to Owner only
  public entry 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 {});
 }