Critical Security Bug
File: lifebank-soroban/contracts/identity/src/lib.rs (line 186)
Problem
IdentityContract::initialize() does not call admin.require_auth() before storing the admin address:
pub fn initialize(env: Env, admin: Address) -> Result<(), Error> {
if Self::is_initialized(env.clone()) {
return Err(Error::AlreadyInitialized);
}
// ⚠️ No admin.require_auth() here
env.storage().instance().set(&DataKey::Admin, &admin);
env.storage().instance().set(&DataKey::OrgCounter, &0u32);
Self::grant_role(env.clone(), admin.clone(), Role::Admin);
...
}
Attack Scenario
On Stellar, smart contract deployment and initialization are separate transactions. Between the moment the contract is deployed and the legitimate deployer calls initialize(), any Stellar address can call initialize(admin=<attacker_address>) and become the permanent admin — with the authority to verify/unverify organizations, award badges, and manage the entire identity registry.
Impact
- Attacker becomes the irrecoverable admin (no admin transfer mechanism exists)
- All legitimate organizations can be unverified; malicious ones can be verified
- The entire on-chain identity and role system is compromised
Fix
pub fn initialize(env: Env, admin: Address) -> Result<(), Error> {
admin.require_auth(); // add this line
if Self::is_initialized(env.clone()) {
return Err(Error::AlreadyInitialized);
}
...
}
Critical Security Bug
File:
lifebank-soroban/contracts/identity/src/lib.rs(line 186)Problem
IdentityContract::initialize()does not calladmin.require_auth()before storing the admin address:Attack Scenario
On Stellar, smart contract deployment and initialization are separate transactions. Between the moment the contract is deployed and the legitimate deployer calls
initialize(), any Stellar address can callinitialize(admin=<attacker_address>)and become the permanent admin — with the authority to verify/unverify organizations, award badges, and manage the entire identity registry.Impact
Fix