Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
Submission Details
Impact: low
Likelihood: medium
Invalid

Lack of Input Validation on _pincode and _isoCode Allows Invalid Oracle Requests

Author Revealed upon completion

Missing input validation on _pincode and _isoCode allows empty strings to be processed, resulting in invalid oracle requests and potential LINK wastage.

Description

  • The requestMintWeatherNFT and _sendFunctionsWeatherFetchRequest functions accept user-supplied location identifiers (_pincode and _isoCode) to fetch current weather data via Chainlink Functions.

  • However, both functions fail to validate these inputs. As a result, a user can pass empty strings (""), triggering oracle calls with malformed or meaningless data. This wastes LINK funds, may return garbage results, or cause unpredictable behavior in the off-chain function logic.

function requestMintWeatherNFT(
string memory _pincode,
string memory _isoCode,
bool _registerKeeper,
uint256 _heartbeat,
uint256 _initLinkDeposit
) external payable returns (bytes32 _reqId) {
@> // No input validation for _pincode and _isoCode
...
_reqId = _sendFunctionsWeatherFetchRequest(_pincode, _isoCode);
}
function _sendFunctionsWeatherFetchRequest(
string memory _pincode,
string memory _isoCode
) internal returns (bytes32 _reqId) {
@> string[] memory _args = new string[](2);
@> _args[0] = _pincode;
@> _args[1] = _isoCode;
...
}

Risk

Likelihood:

  • This will occur whenever a user passes empty strings to requestMintWeatherNFT, whether by accident (bad frontend) or intention (malicious griefing).

  • The oracle request will still be sent and consume LINK + gas, regardless of the input validity.

Impact:

  • Unvalidated inputs can trigger broken or failed Chainlink Function executions, potentially wasting LINK or causing unwanted side effects.

  • Multiple invalid calls can drain LINK balances or spam the Chainlink DON, leading to cost or rate-limit issues.


Proof of Concept

In this test:

  • requestMintWeatherNFT() accepts invalid inputs

  • Triggers an off-chain request to OpenWeather with invalid parameters

  • Wastes resources without error

event WeatherNFTMintRequestSent(address user, string pincode, string isoCode, bytes32 requestId);
function testMintAllowsEmptyPincodeAndIsoCode() public {
string memory emptyPincode = "";
string memory emptyIsoCode = "";
// Expect the function NOT to revert on bad input
vm.expectEmit(true, true, true, true);
emit WeatherNFTMintRequestSent(
address(this), // sender
emptyPincode,
emptyIsoCode,
bytes32(0) // request ID will be overwritten in actual call, so allow wildcard if needed
);
weatherNft.requestMintWeatherNFT{value: 0.01 ether}(
emptyPincode,
emptyIsoCode,
false, // don't register keeper
0, // heartbeat
0 // LINK deposit
);
}

Output:

╰─ forge test --mt testMintAllowsEmptyPincodeAndIsoCode -vv ─╯
[⠊] Compiling...
No files changed, compilation skipped
Ran 1 test for test/WeatherNftForkTest.t.sol:WeatherNftForkTest
[FAIL: log != expected log] testMintAllowsEmptyPincodeAndIsoCode() (gas: 44615)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 11.63ms (1.62ms CPU time)
Ran 1 test suite in 184.16ms (11.63ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/WeatherNftForkTest.t.sol:WeatherNftForkTest
[FAIL: log != expected log] testMintAllowsEmptyPincodeAndIsoCode() (gas: 44615)
Encountered a total of 1 failing tests, 0 tests succeeded

Recommended Mitigation

- function requestMintWeatherNFT(
- string memory _pincode,
- string memory _isoCode,
+ function requestMintWeatherNFT(
+ string memory _pincode,
+ string memory _isoCode,
+ ) external payable returns (bytes32 _reqId) {
+ require(bytes(_pincode).length > 0, "Invalid pincode");
+ require(bytes(_isoCode).length > 0, "Invalid ISO code");
- function _sendFunctionsWeatherFetchRequest(string memory _pincode, string memory _isoCode) internal returns (bytes32 _reqId) {
+ function _sendFunctionsWeatherFetchRequest(string memory _pincode, string memory _isoCode) internal returns (bytes32 _reqId) {
+ require(bytes(_pincode).length > 0, "Invalid pincode");
+ require(bytes(_isoCode).length > 0, "Invalid ISO code");
Updates

Appeal created

bube Lead Judge about 8 hours ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[Invalid] Lack of input validation in `requestMintWeatherNFT`

This is informational. It is user's responsibility to provide correct input arguments. If the user provides incorrect arguments, it will lead to incorrect results, lost funds or failed transaction.

Support

FAQs

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