Severity: Critical
set_admin() and upgrade() are callable by any address. An attacker can replace the admin with their own address or upgrade the contract WASM to malicious code, taking full control of the contract.
- Attacker calls
set_admin(attacker_address). - Contract stores the new admin without verifying the caller is the current admin.
- Attacker now controls all privileged functions including
upgrade().
pub fn set_admin(env: Env, new_admin: Address) {
// ❌ Missing: require_admin(&env);
env.storage().persistent().set(&DataKey::Admin, &new_admin);
}pub fn set_admin(env: Env, new_admin: Address) {
require_admin(&env); // ✅
env.storage().persistent().set(&DataKey::Admin, &new_admin);
}See secure/protected_admin for the full corrected implementation.