Root: Lack of access control and incorrect recipient logic in fulfillMintRequest()
it mints to the caller (msg.sender
) instead of the original user who paid for the mint.
Impact: Enables NFT front-running and theft, causing financial and reputational damage
In the normal flow, a user calls requestMintWeatherNFT()
to initiate an NFT mint based on weather data. Once Chainlink Functions fulfill the weather request, the contract expects the user to call fulfillMintRequest()
to complete the mint.
However, fulfillMintRequest()
mints the NFT to msg.sender
, not the original user who requested it. Since this function is public and not restricted to the original requester, anyone can call it once the request is fulfilled and steal the NFT, especially if they monitor the blockchain for incoming responses.
Likelihood:
This will occur whenever an off-chain Chainlink Functions response is ready, and anyone (not just the original requester) calls fulfillMintRequest()
.
Front-running bots or malicious users can monitor the chain and frontrun the legitimate user to mint the NFT for themselves.
Impact:
The NFT is minted to the wrong address, causing a direct loss of funds/value to the original user.
Loss of user trust and protocol integrity due to unpredictable or malicious minting behavior.
Alice calls requestMintWeatherNFT(...) to mint a Weather NFT.
Her request is stored in the contract, and a Chainlink Functions job is triggered to fetch weather data.
Alice pays the mint price and, optionally, deposits LINK.
After some time, Chainlink Functions completes the job and returns a weather result.
The contract now expects someone to call fulfillMintRequest(requestId) to mint the NFT.
Mallory, a malicious user, watches the blockchain and sees that the weather data has been fulfilled.
She calls fulfillMintRequest(requestId) before Alice does.
Because the contract mints the NFT to msg.sender, not to the original requester (Alice), Mallory receives the NFT.
Track and enforce the original requester in fulfillMintRequest()
by using s_funcReqIdToUserMintReq[requestId].user
, rather than msg.sender
, for the _mint()
call:
There is no check to ensure that the caller of the `fulfillMintRequest` function is actually the owner of the `requestId`. This allows a malicious user to receive a NFT that is payed from someone else.
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.