process_withdraw_excess_lamports is the only owner-authorized operation on token accounts that does not enforce CPI Guard. All 7 others do:
| Operation |
CPI Guard check |
Error |
| Transfer |
Yes |
CpiGuardTransferBlocked |
| Approve |
Yes |
CpiGuardApproveBlocked |
| SetAuthority |
Yes |
CpiGuardSetAuthorityBlocked |
| Burn |
Yes |
CpiGuardBurnBlocked |
| CloseAccount |
Yes |
CpiGuardCloseAccountBlocked |
| UnwrapLamports |
Yes |
CpiGuardTransferBlocked |
| WithdrawExcessLamports |
No |
— |
This means WithdrawExcessLamports can be called via CPI on a token account with CPI Guard enabled, while every other owner-authorized operation is blocked.
UnwrapLamports is the closest analogue (both extract SOL from a token account with owner authorization) and it has the check.
If this is intentional, it might be worth documenting. If not, the fix would be adding the standard check in the token-account branch of process_withdraw_excess_lamports, after validate_owner:
if let Ok(cpi_guard) = account.get_extension::<CpiGuard>() {
if cpi_guard.lock_cpi.into() && in_cpi() {
return Err(TokenError::CpiGuardTransferBlocked.into());
}
}
The CPI Guard test suite (clients/rust-legacy/tests/cpi_guard.rs) covers all 7 other operations but not WithdrawExcessLamports.
process_withdraw_excess_lamportsis the only owner-authorized operation on token accounts that does not enforce CPI Guard. All 7 others do:CpiGuardTransferBlockedCpiGuardApproveBlockedCpiGuardSetAuthorityBlockedCpiGuardBurnBlockedCpiGuardCloseAccountBlockedCpiGuardTransferBlockedThis means
WithdrawExcessLamportscan be called via CPI on a token account with CPI Guard enabled, while every other owner-authorized operation is blocked.UnwrapLamportsis the closest analogue (both extract SOL from a token account with owner authorization) and it has the check.If this is intentional, it might be worth documenting. If not, the fix would be adding the standard check in the token-account branch of
process_withdraw_excess_lamports, aftervalidate_owner:The CPI Guard test suite (
clients/rust-legacy/tests/cpi_guard.rs) covers all 7 other operations but notWithdrawExcessLamports.