A high severity vulnerability has been identified in the CapitalPool contract's approve function. This vulnerability allows any external address to call the approve function, setting a maximum allowance for the TokenManager. This behavior contradicts the contract's intended design, as indicated by its natspec comment stating "@notice only can be called by token manager". The ability for an external account to be able to call such a critical function opens up more surface area for potential attacks.
The approve
function in the CapitalPool contract can be called by any address, including unauthorized ones. The function sets the allowance for the TokenManager to the maximum possible value (type(uint256).max
) regardless of who calls it. This is demonstrated by the following test:
The test passes, indicating that the vulnerability exists. The test output shows:
The test can be ran in the following test suite to confirm its output.
The test reveals two issues:
Lack of Access Control: The approve
function can be called by any address, not just the contract owner or authorized users.
Unlimited Allowance Setting: The function sets the allowance to the maximum possible value (type(uint256).max
) for any caller.
This vulnerability raises several security concerns:
Violation of Principle of Least Privilege: The contract allows more access than necessary, which goes against security best practices.
Potential for Unexpected Interactions: In a complex system, this could interact with other components in unforeseen ways.
Misleading Behavior: Users and other contracts interacting with CapitalPool might assume that approvals are restricted, leading to incorrect assumptions about the system's state.
Auditability Issues: It becomes harder to track legitimate approvals vs. unauthorized ones.
Contradiction of Intended Design: The behavior contradicts the natspec comment, which could lead to misunderstandings and potential misuse of the contract.
Foundry: Used for contract compilation and running the test suite that revealed the vulnerability.
Manual Code Review: The vulnerability was identified through careful examination of the contract code and analysis of the test results.
To address this vulnerability, we recommend the following actions:
Implement Strict Access Control: Add access control to the approve
function. This can be done by using OpenZeppelin's Ownable
contract and adding the onlyOwner
modifier:
Consider implementing a more granular access control system, possibly allowing only the TokenManager to call this function, as suggested by the natspec comment.
Review and update all natspec comments to ensure they accurately reflect the intended and actual behavior of the contract.
By implementing these recommendations, the security of the CapitalPool contract and the overall system will be significantly improved, mitigating the risks associated with unauthorized approvals and aligning the contract's behavior with its intended design.
This is at most low severity, even though giving max approvals shouldn't be permisionless, the respective tokenManager address is retrieved from the TadleFactory contract whereby the trusted guardian role is responsible for deploying such contracts as seen [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/factory/TadleFactory.sol#L68). Since the user still has to go through the PreMarkets/DeliveryPlace contracts to perform market actions, this max approval cannot be exploited.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.