Skip to content

[contracts/identity] initialize() has no require_auth() — any caller can claim admin before the deployer #866

@Emeka000

Description

@Emeka000

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);
    }
    ...
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions