-
Notifications
You must be signed in to change notification settings - Fork 0
unforgiven - Unbound recursive function call can use unlimited gas and break hats operation #96
Comments
Tentative solution is to cap the number of nested trees at a reasonable value that ensures the tippy top hat will always be able to exercise its admin rights over the lowest tree, eg
We can calculate (1) and (2) by incrementing a counter each step up as we traverse the cc @zobront |
Will need to test out gas impacts of higher numbers of nested trees to find a good cap value. |
@spengrah Agree this is the best solution. Two questions:
|
Great questions @zobront. Overall, I would strongly prefer to not have different versions across different networks, so will likely constrain cheaper / higher capacity networks based on the limits of more expensive networks. That said, I think it should be up to the user org to determine the cost their willing to spend to add more trees, so overall I think I'm likely to set the cap based on block size rather than gas price. |
@zobront after further research, it's actually going to be pretty expensive to enforce a cap. We can relatively easily count the depth of the would-be parent tree (step 2 above) since we can traverse up the "linked list" of the linkedTreeAdmin mapping. But counting the depth of the would-be child would require a new data model since we need to count down. So, at this point in the process, what I think is most appropriate is to document this risk and recommend that any tophats that have more than N (say, 10) nested trees below them not grant any authorities to the trees below N. |
@zobront We figured out a fix! Was thinking that the additional data structure needed to count down would be onerous, but realized that we can just add another mapping that goes the other way, basically creating a doubly-linked list without having to impact the first mapping. So we can now count down pretty easily. |
zobront added the "Fix Approved" label |
unforgiven
medium
Unbound recursive function call can use unlimited gas and break hats operation
Summary
some of the functions in the Hats and HatsIdUtilities contracts has recursive logics without limiting the number of iteration, this can cause unlimited gas usage if hat trees has huge depth and it won't be possible to call the contracts functions. functions
getImageURIForHat()
,isAdminOfHat()
,getTippyTopHatDomain()
andnoCircularLinkage()
would revert and because most of the logics callings those functions so contract would be in broken state for those hats.Vulnerability Detail
This is function
isAdminOfHat()
code:As you can see this function calls itself recursively to check that if user is wearer of the one of the upper link hats of the hat or not. if the chain(depth) of the hats in the tree become very long then this function would revert because of the gas usage and the gas usage would be high enough so it won't be possible to call this function in a transaction. functions
getImageURIForHat()
,getTippyTopHatDomain()
andnoCircularLinkage()
has similar issues and the gas usage is depend on the tree depth. the issue can happen suddenly for hats if the top level topHat decide to add link, for example:Impact
it won't be possible to perform actions for those hats and funds can be lost because of it.
Code Snippet
https://github.com/Hats-Protocol/hats-protocol/blob/fafcfdf046c0369c1f9e077eacd94a328f9d7af0/src/Hats.sol#L831-L883
https://github.com/Hats-Protocol/hats-protocol/blob/fafcfdf046c0369c1f9e077eacd94a328f9d7af0/src/Hats.sol#L1022-L1067
https://github.com/Hats-Protocol/hats-protocol/blob/fafcfdf046c0369c1f9e077eacd94a328f9d7af0/src/HatsIdUtilities.sol#L194-L200
https://github.com/Hats-Protocol/hats-protocol/blob/fafcfdf046c0369c1f9e077eacd94a328f9d7af0/src/HatsIdUtilities.sol#L184-L188
Tool used
Manual Review
Recommendation
code should check and make sure that hat levels has a maximum level and doesn't allow actions when this level breaches. (keep depth of each tophat's tree and update it when actions happens and won't allow actions if they increase depth higher than the threshold)
The text was updated successfully, but these errors were encountered: