Weather Witness

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

Missing Access Control in fulfillMintRequest

Root: The mint function lacks any caller restriction and can be called by anyone.

Impact: Any malicious user can call this function, minting NFTs illegitimately without valid fulfillment or weather data.

Description

  • Normally, this function should only be called by the Chainlink oracle once valid weather data is received, ensuring the integrity of NFT metadata.

  • However, because there is no restriction on who can call fulfillMintRequest, any observer can invoke this function with a known or guessed request ID—causing unauthorized NFT mints.

// Root cause in the codebase with @> marks to highlight the relevant section
@> function fulfillMintRequest(bytes32 requestId) external {
...
_safeMint(to, newTokenId);
...
}

CopyEdit

// Root cause in the codebase with @> marks to highlight the relevant section

Risk

Likelihood:

  • Moderate—anyone watching requestId emissions can act.

Impact:

  • NFT collection polluted with unauthorized or incorrect tokens.

  • Users receive NFTs they didn’t request, breaking trust and fairness.

Proof of Concept: Because the attacker can observe a valid requestId in the event logs, they can immediately call the fulfillMintRequest() method. Without an access control check, this leads to unauthorized NFT minting using possibly invalid or no weather data at all.

// Attacker listens to Chainlink requestId event
bytes32 leakedRequestId = sniffFromLogs();
// Then calls the fulfill function themselves
weatherNft.fulfillMintRequest(leakedRequestId); // No permission required

Recommended Mitigation: This access control ensures only Chainlink (or the off-chain trusted oracle address) can call the fulfillMintRequest function. It prevents any arbitrary caller from triggering the minting process, thus protecting against spoofed or early fulfillment and preserving the authenticity of NFTs.

- function fulfillMintRequest(bytes32 requestId) external {
+ function fulfillMintRequest(bytes32 requestId) external {
+ require(msg.sender == address(chainlinkOracle), "Only Chainlink can fulfill");
Updates

Appeal created

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

Lack of ownership check in `fulfillMintRequest` function

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.

Support

FAQs

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