Impact: Medium, since the owner can still bridge his NFT
Likelihood: High, since it can be performed by almost anyone
_ccipReceive()
is a critical function in the CCIP system which is invoked on the receiver contract by the CCIP router.
The issue is found in the passing of msg.sender
as the _sender
parameter of the onlyAllowlisted
modifier from KittyBridgeBase
.
However, in order for the function not to revert, msg.sender
can only be the address of the CCIP router because of the following public function exposed by CCIPReceiver
(that KittyBridge inherits) that has the onlyRouter
modifier:
This makes possible for anyone to mint a cat NFT by directly calling the router without passing from KittyConnect:bridgeNftToAnotherChain()
, the only function that is responsible for checking that the caller actually owns the NFT.
Refer to the following diagram: https://drive.google.com/file/d/1JolPeIiFjYYS1Um8TkUWhMSTg0oa2IWj/view?usp=sharing
To always make sure that the NFT is owned and burn by the catOwner on the source chain, we must add proper access control to the functions listed below:
protect KittyBridge:bridgeNftWithData()
to only allow the KittyConnect contract to call it
Change the second parameter of the onlyAllowListed
as follows to pass the actual sender of the message (which will be the KittyBridge
on the source chain)
Of course, the KittyBridge
on the destination chain, must allow-list the address of the KittyBridge
on the source chain in his allowlistedSenders
mapping.
The any2EvmMessage.sender
is safely set by the CCIP router on the source chain:
Also refer to the following ChainLink CCIP official example:
https://docs.chain.link/ccip/tutorials/programmable-token-transfers-defensive#tutorial
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.