Open c4-submissions opened 1 year ago
DadeKuma marked the issue as duplicate of #214
DadeKuma marked the issue as sufficient quality report
0xean marked the issue as unsatisfactory: Invalid
Indeed, I had an oversight on this report that the panic would be recovered, so such impact agreed is QA, similar to my Low-8 or Low-21. Nevertheless, I would still argue the report to remains at High
severity because of the ballot(s) that might never finalize
impact, has vote would be missing, which would translate in user funds loss
. (ccing: @lumtis since on 214
he didn't had the same impact and he should be made aware of the ballot finalization issue which is more critical)
214 I don't think this report should be a duplicated of mine, as while identifying properly the panic (which recovered, so QA), the warden doesn't identify the most important impact which is the fact that affected ballot(s) might never finalize due to the missing vote.
523
I think this issue is a valid duplicate, while I would recommend the @0xean to kindly consider my submission as selected report
for the final report (if valid) as it provides better description, impacts, PoC (also coded) and recommendations.
From my understanding updating the observers would be done when CCTX are in paused state, not while ongoing votes on a ballet are being conducted. Happy to get the sponsors thoughts here before final judgement, but most likely will leave as judged.
lumtis (sponsor) confirmed
@lumtis - I don't see proof that this leads to a loss of user funds if CCTXs are paused, can you explain to me how that occurs which is needed for this to be considered as H severity?
0xean changed the severity to 2 (Med Risk)
0xean marked the issue as selected for report
@lumtis - I don't see proof that this leads to a loss of user funds if CCTXs are paused, can you explain to me how that occurs which is needed for this to be considered as H severity?
Yes, I confirmed this is an issue that need to be fixed but on the severity I agree to decrease to med risk
0xean marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/types/ballot.go#L27-L35
Vulnerability details
Description
The function
GetVoterIndex
is used in multiple places to get the index of a specific Observer from the Voter List. The problem is that the caller is assuming the function will always succeed, but clearly there is a possibility where theObserver address could not be found
, which would return anindex of -1
, which will effectivelly make the program panic.[Instance 1]
Observer::BallotByIdentifier
This one is safe since the GetVoterIndex is called from the same ballot instance it is iterating over, so it's impossible to not find the index in such case.
https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/keeper/ballot.go#L94
[Instance 2]
Observer::BuildRewardsDistribution
Safe, for the same reason as instance 1.
https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/types/ballot.go#L82 https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/types/ballot.go#L92
[Instance 3]
Observer::HasVoted
Even if this is public function, it's actually a private one and only used by
AddVote
, so share the same risk.https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/types/ballot.go#L22
[Instance 4]
Observer::AddVote
This is the
spicy one
which has some risks. This is called by AddVoteToBallot which is then called in6 differents places
(VoteOnObservedInboundTx, VoteOnObservedOutboundTx, CreateTSSVoter 1, CreateTSSVoter 2, AddBlameVote and AddBlockHeader), with the ballot instance and address being looked at coming in different parameters and from different sources, so here there is posibility the issue could occur.https://github.com/code-423n4/2023-11-zetachain/blob/main/repos/node/x/observer/types/ballot.go#L16
Impact
zetaclientd
would panic (so crash) if the indicated code path is activated in Instance 4.might never be able to be finalized
depending on how many Observer have been updated and what is the threshold. A ballot never finalizing would mean the CCTX never reaching consensus and funds loss, which is why this seems to warrantHigh
severity.Proof of Concept
Here is a PoC when using
AddBlockHeader
, but there might be other cracks coming from the 5 other places I identified for Instance 4 where this code path can be activated.1)
AddBlockHeader
gRPC endpoint is called by Observer A. Current Observer list is A,B. Since this is the first vote, the ballot is created byFindBallot
with observers list being A,B. 2) Afterward,UpdateObserver
gRPC endpoint is called to update Observer B for reasonObserverUpdateReason_AdminUpdate
. This update Observer B address to now be C in the theObserverMapper
and the observer list. 3)AddBlockHeader
is called by Observer C (which was previously B). The ballot created previously is retrieved andAddVoteToBallot
is called, which in turns callballot.AddVote(C,...)
, which in turns callHasVoted
which will panic againstreturn m.Votes[index] != VoteType_NotYetVoted
since index will be -1, as C is not in the ballot Observer list.Coded PoC
In order to demostrate my point explained before, I coded it in the following unit test. With the original code it will panic, while by adding my recommendation it will not and recover.
Call stack
Recommended Mitigation Steps
The probability of the indicated negative impacts happening as soon as
UpdateObserver
is pretty high depending on the blockchain activity (and ballot currently in progress), but callingUpdateObserver
should not happen often and can only be triggered by theAdmins Group2
(multi-sig).Granted that the scenario exposed in my PoC might be rare, I haven't taken the time to investigate all the other coner cases where this code path can be activated, which raise doubts on the frequency such scenario can happen which is another reason why it should be mitigated.
I would recommend todo the following changes in order to fix the panic in
HasVoted
andAddVote
at least which seems to present some risks. That will not resolve the issue that impacted ballot might never been able to finalize. A way to mitigate this would be to update also the ballot when updating the observer address.Assessed type
Invalid Validation