Root + Impact
Description:
The Vault resource stores secret as a plaintext String in global storage.
Even though get_secret() enforces ownership checks, anyone can bypass these by directly reading the resource off-chain using borrow_global from a full node or indexer.
struct Vault has key {
    @> secret: String
}
Risk
Likelihood:
- 
Public blockchain data is globally visible. 
- 
Any node, indexer, or explorer can read the secretfield without callingget_secret.
 
Impact:
- 
Privacy breach — all secrets stored are in plaintext. 
- 
Once revealed on-chain, cannot be removed or hidden. 
Proof of Concept
Test Contract :
#[test(owner = @0xcc, attacker = @0x999)]
fun test_secret_is_readable_offchain(owner: &signer, attacker: &signer) acquires Vault {
    use aptos_framework::account;
    account::create_account_for_test(signer::address_of(owner));
    account::create_account_for_test(signer::address_of(attacker));
    
    let my_secret = b"super_private";
    set_secret(owner, my_secret);
    
    let vault = borrow_global<Vault>(signer::address_of(owner));
    
    assert!(vault.secret == string::utf8(my_secret), 1001);
}
TestOutput:
SCATERLABs/Auditing/FirstFlight/2025-07-secret-vault$ aptos move test --filter test_secret_is_readable_offchain
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING aptos-secret-vault
Running Move unit tests
[ PASS    ] 0x234::vault::test_secret_is_readable_offchain
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
  "Result": "Success"
}
SCATERLABs/Auditing/FirstFlight/2025-07-secret-vault$ 
Recommended Mitigation:
In Blockchain everything will be public so better to use encrypted format..
- struct Vault has key {
-     secret: String
- }
+ struct Vault has key {
+     // Store encrypted secret or hash instead of plaintext
+     secret_hash: vector<u8>
+ }
- public entry fun set_secret(caller: &signer, secret: vector<u8>) {
-     let secret_vault = Vault { secret: string::utf8(secret) };
-     move_to(caller, secret_vault);
-     event::emit(SetNewSecret {});
- }
+ public entry fun set_secret(caller: &signer, secret: vector<u8>) {
+     // Off-chain: secret should be hashed or encrypted before being passed here
+     let secret_vault = Vault { secret_hash: secret };
+     move_to(caller, secret_vault);
+     event::emit(SetNewSecret {});
+ }