The current implementation of #[view] get_secret(address)
does not authenticate the caller. Instead, it takes an address
argument and asserts that it equals the hardcoded @owner
. Any user can simply pass @owner
as the parameter to the function and obtain the owner’s secret. This creates a direct logic-level authorization bypass.
The function signature accepts a free address
parameter instead of a &signer
, so it has no knowledge of who is calling it.
The check assert!(caller == @owner, NOT_OWNER)
validates only that the argument equals @owner
, not that the transaction signer is the owner.
Returning the stored String
directly exposes the secret to any caller who passes @owner
.
Likelihood:
Every call to get_secret
only checks the argument, not the actual caller. This means the bypass will occur every time an attacker supplies @owner
as input.
Any user with knowledge of the owner
address (trivial to obtain from blockchain data) can perform this call without restriction.
Impact:
Any attacker can retrieve the owner’s secret without being authorized.
This invalidates the “only the owner may retrieve” guarantee in the project specification.
When combined with the design-level confidentiality flaw, it means that both off-chain and on-chain access controls fail.
This test demonstrates that a non-owner account (@0x123
) can read the owner’s secret.
Replace the address
parameter with an authenticated signer:
Alternatively, if #[view] is required:
Do not expose sensitive plaintext in a view function, as these bypass signer authentication by design.
Instead, expose only non-sensitive metadata (e.g., “secret exists” flag, hash, or ciphertext length).
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.