Open c4-submissions opened 10 months ago
minhquanym marked the issue as primary issue
minhquanym marked the issue as sufficient quality report
d1ll0n (sponsor) acknowledged
d1ll0n marked the issue as disagree with severity
I think this could be a good QA finding but I wouldn't consider it medium severity, or even fixable. Allowing anyone to change the sanctions list address would only replace this issue with a much worse one, namely that the Wildcat team would be able to block lenders from markets.
Also worth noting that the sanctions list can not be paused as suggested in #138 - the effect of this issue (ignoring the possibility of a malicious owner - only considering the key being lost) would just be that the contract stops adding new sanctioned addresses.
I'm new to the +Backstage, and this is my first +Backstage comment. I'm not sure if I'm allowed to reply to the sponsor's comment for now. If not, please do not suspend my +Backstage privileges.
As the sponsor said:
Allowing anyone to change the sanctions list address would only replace this issue with a much worse one, namely that the Wildcat team would be able to block lenders from markets.
Please let me clarify the sponsor's comment with this excerpted part from the Recommended Mitigation Steps
section:
The
chainalysisSanctionsList
parameter in theWildcatSanctionsSentinel
contract should be a state variable allowing authorized users (e.g., the protocol owner) to update it when necessary.
Specifically, the report suggested that only authorized staff (e.g., the Wildcat
protocol owner/admin) should be able to update the chainalysisSanctionsList
parameter, not any unauthorized user.
I raised this issue because the SanctionsList
contract implements the critical single-step functions: renounceOwnership() and transferOwnership(). If one of them is executed incorrectly (by mistakes or human errors), that could brick the SanctionsList
contract eternally.
As the sponsor said:
The Wildcat team would be able to block lenders from markets.
I'm not arguing that.
However, if the SanctionsList
cannot add or remove sanctioned addresses, this can directly affect Wildcat
's essential functions relying on it, including WildcatSanctionsEscrow::canReleaseEscrow()
, WildcatMarketConfig::nukeFromOrbit()
, WildcatMarketConfig::stunningReversal()
, WildcatMarketWithdrawals::executeWithdrawal()
, and their dependency functions.
Of course, the Wildcat
team might be able to block lenders from markets manually, but the incident will break the protocol functionality forever. Moreover, this also reduces the transparency and/or decentralization of managing sanctioned lenders.
For this reason, relying on the third party's security (Chainalysis
) should not be the best security idea of the Wildcat
protocol.
My suggested solution can fully fix the vulnerability without leading to other issues.
Please re-consider this excerpted part from the Recommended Mitigation Steps
section thoroughly:
The
chainalysisSanctionsList
parameter in theWildcatSanctionsSentinel
contract should be a state variable allowing authorized users (e.g., the protocol owner) to update it when necessary.Since the
Sentinel
is a singleton contract, updating thechainalysisSanctionsList
parameter at theSentinel
would be effective for all deployedMarket
contracts,MarketController
contracts, andMarketControllerFactory
contracts discussed previously.
It`s worth to mention that the Chainalysis: Sanctions Oracle's owner is a simple walllet, not a multisig, not a timelock. Therefore, the concern that it could be compromised is valid. (But this external dependency is not in scope of this contest.)
On the other hand, the proposed solution that only authorized staff (e.g., the Wildcat protocol owner/admin) should be able to set a new sanctions list address adds a second point of failure. Therefore, not a viable solution.
As this is not a bug of the protocol itself and cannot be circumvented easily in a satisfactory way, QA seems most appropriate.
@serial-coder
I want to assure you that your comment before post-judging QA did not have any impact on my assessment of severity.
As a fresh backstage warden, mistakes can happen. All the best for your journey on C4.
MarioPoneder changed the severity to QA (Quality Assurance)
MarioPoneder marked the issue as grade-a
Lines of code
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L14 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L42 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsEscrow.sol#L26 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L75 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L94 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketWithdrawals.sol#L164
Vulnerability details
The
chainalysisSanctionsList
parameter of theWildcatSanctionsSentinel
contract is an immutable variable. It will be unchangeable if Chainalysis'sSanctionsList
contract is down, affecting several essential functions in theWildcat
protocol to malfunction.Proof of Concept
In the
WildcatSanctionsSentinel
contract, thechainalysisSanctionsList
is declared immutable, pointing to Chainalysis'sSanctionsList
contract. Therefore, no one can update it if necessary after theSentinel
contract is deployed.The
chainalysisSanctionsList
parameter is employed in the criticalWildcatSanctionsSentinel::isSanctioned()
to query the sanction status of all lenders in everyMarket
contract throughout the protocol.I noticed that Chainalysis's
SanctionsList
contract implements the critical single-step functions: renounceOwnership() and transferOwnership(). If one of them is somehow executed incorrectly, that could brick theSanctionsList
contract eternally.Consequently, the
Wildcat
protocol's functions will be directly damaged since no one can update thechainalysisSanctionsList
parameter.https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L14
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L42
Impact
The following lists essential functions that require the oracle data sourced from Chainalysis's
SanctionsList
contract.WildcatSanctionsEscrow
contractWildcatSanctionsEscrow::canReleaseEscrow()
WildcatMarket
contractWildcatMarketConfig::nukeFromOrbit()
WildcatMarketConfig::stunningReversal()
WildcatMarketWithdrawals::executeWithdrawal()
If Chainalysis's
SanctionsList
contract is down, the above functions could malfunction. For instance, no one, including the borrower and theWildcat
protocol owner, can block any sanctioned lenders from interacting with their markets.Moreover, the bricking of the
SanctionsList
will affect all deployedMarket
contracts,MarketController
contracts, andMarketControllerFactory
contracts as they point to the singletonSentinel
contract.Tools Used
Manual Review
Recommended Mitigation Steps
The
chainalysisSanctionsList
parameter in theWildcatSanctionsSentinel
contract should be a state variable allowing authorized users (e.g., the protocol owner) to update it when necessary.Since the
Sentinel
is a singleton contract, updating thechainalysisSanctionsList
parameter at theSentinel
would be effective for all deployedMarket
contracts,MarketController
contracts, andMarketControllerFactory
contracts discussed previously.Assessed type
Oracle