Incorrect account bindings allows admin to deduct from vester
Description
The cancel_vesting()
instruction allows an admin signer to cancel the vesting on a vester_ta.owner
. Since the vest
account is not properly bound to the config
and vester_ta
, it is possible for an admin to cancel the Vesting
acount for an unrelated vester, deducting the incorrect amount from that vester's total.
The cancel_vesting()
instruction subtracts the vested amount from config as follows:
pub fn cancel_vesting(&mut self) -> Result<()> {
self.config.vested = self
.config
.vested
.checked_sub(self.vest.amount)
.ok_or(VestingError::Underflow)?;
self.vesting_balance.total_vesting_balance = self
.vesting_balance
.total_vesting_balance
.checked_sub(self.vest.amount)
.ok_or(VestingError::Underflow)?;
Ok(())
}
However, the self.vest.amount
can be used from an unrelated vester since the vest
can refer to itself for the vester_ta
used in the account seed.
#[account(
mut,
close = admin,
has_one = config, // This check is arbitrary, as ATA is baked into the PDA
seeds = [VEST_SEED.as_bytes(), config.key().as_ref(), vest.vester_ta.key().as_ref(), vest.maturation.to_le_bytes().as_ref()],
bump = vest.bump
)]
vest: Account<'info, Vesting>,
pub struct Vesting {
pub vester_ta: Pubkey,
pub config: Pubkey,
pub amount: u64,
pub maturation: i64,
pub bump: u8,
}
If an admin uses a vest
account with the wrong vester_ta
, the incorrect amount would be subtracted from the vesting balance.
Impact
The issue requires administrative access, lowering its likelihood. The impact is High since balances can be incorrectly deducted.
Recommendations
Add a constraint in the account macro on the vest
to ensure has_one = vester_ta
.
Remediation
This issue has been acknowledged by Wormhole Foundation, and a fix was implemented in commit 2e111968↗.