Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Request ID Collision and Reuse Risk in Weather NFT Contract

Description

The contract lacks protection against request ID collisions and reuse in the Oracle request system, potentially leading to data corruption or manipulation.

Risk

Severity: Medium
Likelihood: Medium

Summary

The contract's request ID handling mechanism doesn't implement safeguards against ID collisions or reuse, which could lead to weather data being incorrectly mapped to NFTs.

Vulnerability Details

Root Cause:

s_funcReqIdToTokenIdUpdate[_reqId] = _tokenId;
s_funcReqIdToUserMintReq[_reqId] = UserMintRequest({...});

Initial State:

  1. Contract manages multiple concurrent oracle requests

  2. Request IDs are generated using Chainlink's system

Attack Scenario:

  1. Multiple weather update requests are made

  2. Request ID collision occurs due to similar input parameters

  3. Later request overwrites earlier request's data

  4. NFTs receive incorrect weather updates

Proof of Concept

function testRequestIdCollision() public {
// Setup two NFTs
bytes32 reqId1 = weatherNft.requestMintWeatherNFT{value: 1 ether}(
"123456",
"US",
false,
3600,
0
);
// Simulate collision by using same parameters
bytes32 reqId2 = weatherNft.requestMintWeatherNFT{value: 1 ether}(
"123456",
"US",
false,
3600,
0
);
// If collision occurs, second request overwrites first
assertNotEq(reqId1, reqId2, "Request ID collision detected");
}

Impact

  • Data corruption

  • Incorrect weather updates

  • Lost oracle responses

  • Potential NFT value manipulation

  • System reliability compromised

Tools Used

  • Manual Review

Recommendations

Add request ID tracking and validation:

contract WeatherNft {
mapping(bytes32 => bool) private usedRequestIds;
error RequestIdAlreadyUsed(bytes32 requestId);
function validateAndTrackRequestId(bytes32 requestId) internal {
if (usedRequestIds[requestId]) {
revert RequestIdAlreadyUsed(requestId);
}
usedRequestIds[requestId] = true;
}
function _sendFunctionsWeatherFetchRequest(
string memory _pincode,
string memory _isoCode
) internal returns (bytes32 _reqId) {
// ...existing code...
_reqId = _sendRequest(
req.encodeCBOR(),
s_functionsConfig.subId,
s_functionsConfig.gasLimit,
s_functionsConfig.donId
);
validateAndTrackRequestId(_reqId);
}
// Add cleanup
function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
// ...existing code...
// Cleanup after processing
delete usedRequestIds[requestId];
}
}
Updates

Appeal created

bube Lead Judge 4 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Multiple tokens for one `requestId`

The `WeatherNFT::fulfillMintRequest` allows a malicious user to call multiple times the function with the same `requestId`.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.