Vast Mahogany Fox
High
A flawed authorization check in the _acceptAdmin()
function will prevent legitimate admin transfers and potentially allow unauthorized admin access, as the function checks if msg.sender
is address(0) instead of validating if pendingAdmin
is address(0), breaking the intended admin transfer flow.
In Numa/contracts/lending/Unitroller.sol#L137-L138
he admin acceptance authorization check is implemented incorrectly
if (msg.sender != pendingAdmin || msg.sender == address(0)) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);
}
- Admin calls
_setPendingAdmin()
to assign a newpendingAdmin
pendingAdmin
is set to a non-zero address
The vulnerability is self-contained within the contract and does not require any external protocol conditions or state changes to be exploited.
- Admin initiates admin transfer by calling
_setPendingAdmin(newAdmin)
pendingAdmin
is set tonewAdmin
address- When legitimate
newAdmin
tries to call_acceptAdmin()
:// Given: msg.sender == pendingAdmin (legitimate call) if (msg.sender != pendingAdmin || msg.sender == address(0)) { return fail(Error.UNAUTHORIZED, ...); }
- The check will always fail for the legitimate pending admin because:
- First condition
msg.sender != pendingAdmin
is false (good) - Second condition
msg.sender == address(0)
is false (good) - But
msg.sender
is being checked instead ofpendingAdmin
- First condition
- This breaks the admin transfer mechanism.
The protocol's admin transfer functionality is broken, leading to:
- Legitimate admin transfers being impossible to complete
- Potential privilege escalation if combined with other contract vulnerabilities
- Risk to core protocol security as this affects critical admin functions:
- Implementation upgrades via
_setPendingImplementation()
- Admin transfers via
_setPendingAdmin()
- Any admin-protected functionality in the delegated implementation
- Implementation upgrades via
No response
- Replace the current condition:
if (msg.sender != pendingAdmin || msg.sender == address(0)) {
With:
if (msg.sender != pendingAdmin || pendingAdmin == address(0)) {
- Consider implementing explicit require statements for better error handling:
require(pendingAdmin != address(0), "PendingAdmin cannot be zero address");
require(msg.sender == pendingAdmin, "Caller must be pendingAdmin");