The contract stores the user’s secret directly on-chain in plaintext. On Aptos, all global state is publicly accessible: full nodes, indexers, or anyone running an RPC can read resources without authentication. This means the stored “secret” is never actually secret, regardless of access controls in the module. Once published, the data becomes permanently visible and cannot be hidden or deleted.
Design issue: Vault.secret: String
is stored in a key
resource under the user’s account. By definition, resources in global storage are public.
Even if get_secret
were perfectly restricted, the plaintext remains retrievable directly from node APIs or indexers.
Likelihood:
Every time a user calls set_secret
, the secret is committed to Aptos global storage as plaintext. This is immediately included in the public ledger and becomes accessible to all full nodes and indexers.
Any third party running a node, RPC endpoint, or indexer routinely synchronizes global storage and can query the Vault
resource without restrictions. This makes retrieval of the secret a standard, guaranteed operation whenever someone inspects account state.
Impact:
Confidentiality is completely broken: Any actor can obtain the secret through off-chain queries, without interacting with the smart contract.
Exposure is permanent: even deleting or overwriting later cannot erase the historical leak.
Direct RPC query
returns the secret
field in plaintext.
Indexer query
Any indexer service can fetch and display the secret for arbitrary accounts.
Historical chain data
Even if the resource is later cleared or updated, the original plaintext is preserved in past ledgers.
After calling set_secret
, the following resource is stored:
Using the Aptos CLI or REST API, anyone can read this value:
This command outputs the secret directly, no authentication required.
If confidentiality is required:
Never store secrets as plaintext on-chain.
Encrypt client-side before submission (e.g., AES-GCM / XChaCha20-Poly1305).
Store only ciphertext and metadata (nonce, hash).
Provide only the ciphertext via get_secret
, users must decrypt off-chain with their private key.
If confidentiality is not required:
Explicitly document that secrets are public.
Rename functions/structs to avoid misleading users into thinking secrecy is provided.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.