Vaults can be created permissionlessly by anyone. A malicious vault creator has a couple of ways to give ultimited appoval over the vault's underlying asset to a contract in his control. This way, once the vault has enough deposits, the owner can rugpull all the funds.
Proof of Concept
The places the bad actor can use for this attack are:
Here we can see in line #281 that the contract gives max approval to the yieldVault_ contract, which is supplied by the owner when creating a Vault, over the underlying asset of the vault. The Vault is created trough the VaultFactory, but that contract does not make any sanity check over the addresses passed in to the constructor.
This way, the malicious owner can craft a yieldVault_ contract with a rugpull function he can call anytime to drain all the funds from the vault and send them to him. And of course all the underlying assets deposited in the yieldVault_ contract could be drained too.
Here is the same for the liquidationPair_ contract, which is given max approval in line #677. Same case as before, the address is supplied by the malicious owner of the vault, who can craft a contract with a rug pull function that transfers all the underlying assets to him.
Tools Used
Manual review
Recommended Mitigation Steps
A solution I can think of is checking the code of the deployed contracts in both the yieldVault_ and liquidationPair_ addresses against a set of whitelisted implementations of each contract. This would prevent the owner from setting maliciously crafted contracts that would allow him to rug pull the funds.
Lines of code
https://github.com/GenerationSoftware/pt-v5-vault/blob/b1deb5d494c25f885c34c83f014c8a855c5e2749/src/Vault.sol#L254-L296 https://github.com/GenerationSoftware/pt-v5-vault/blob/b1deb5d494c25f885c34c83f014c8a855c5e2749/src/Vault.sol#L665-L683
Vulnerability details
Impact
Vaults can be created permissionlessly by anyone. A malicious vault creator has a couple of ways to give ultimited appoval over the vault's underlying
asset
to a contract in his control. This way, once the vault has enough deposits, the owner can rugpull all the funds.Proof of Concept
The places the bad actor can use for this attack are:
The constructor
Here we can see in line #281 that the contract gives max approval to the
yieldVault_
contract, which is supplied by the owner when creating a Vault, over the underlying asset of the vault. The Vault is created trough the VaultFactory, but that contract does not make any sanity check over the addresses passed in to the constructor.This way, the malicious owner can craft a
yieldVault_
contract with a rugpull function he can call anytime to drain all the funds from the vault and send them to him. And of course all the underlying assets deposited in theyieldVault_
contract could be drained too.setLiquidationPair
Here is the same for the
liquidationPair_
contract, which is given max approval in line #677. Same case as before, the address is supplied by the malicious owner of the vault, who can craft a contract with a rug pull function that transfers all the underlying assets to him.Tools Used
Manual review
Recommended Mitigation Steps
A solution I can think of is checking the code of the deployed contracts in both the
yieldVault_
andliquidationPair_
addresses against a set of whitelisted implementations of each contract. This would prevent the owner from setting maliciously crafted contracts that would allow him to rug pull the funds.Assessed type
Rug-Pull