Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

[H-4]Excessive Owner Privileges Create Centralized Trust Assumption Risk

[H-4] Excessive Owner Privileges Create Centralized Trust Assumption Risk

Description

The WeatherNftcontract is designed to produce NFTs that represent real-world weather conditions at specific locations, with the core value proposition being accurate and trustworthy weather representation.

However, the contract implements multiple critical owner-only functions without any governance mechanism, timelock delays, or multi-signature requirements, creating a centralized trust assumption that undermines the protocol's reliability and security.

// Owner can change the JavaScript source code that fetches weather data
function updateSource(string memory newSource) external onlyOwner {
@> s_functionsConfig.source = newSource;
}
// Owner can change other critical infrastructure parameters with no oversight
function updateSubId(uint64 newSubId) external onlyOwner {
@> s_functionsConfig.subId = newSubId;
}
function updateEncryptedSecretsURL(bytes memory newEncryptedSecretsURL) external onlyOwner {
@> s_functionsConfig.encryptedSecretsURL = newEncryptedSecretsURL;
}

Risk

Likelihood: High

  • The contract has multiple centralized control points with no safeguards or checks.

  • No timelock delays or governance mechanisms are implemented for critical parameter changes.

  • Weather data relies on a single API source controlled by the owner's JavaScript code.

Impact: High

  • A malicious or compromised owner could silently modify the oracle source code to return fraudulent weather data.

  • Users have no verification mechanism to ensure the integrity of weather data that determines their NFT's properties.

  • The entire value proposition of the NFT collection could be compromised by a single actor.

Proof Of Concept

The test bellow shows that the owner can basically manipulate all the important functionalities of the contract, without the users even knowing.

Note: You may need to deploy your own contract instance, set up a Chainlink Automation subscription and modify the configs so that this test may work properly:

function test_owner_can_change_data_without_any_constrains() public{
// Owner decides to manipulate weather data to always show "SUNNY"
string memory maliciousSource = "return Functions.encodeUint8(uint8(WeatherNftStore.Weather.SUNNY));";
// Owner can change the source without delay or oversight
vm.prank(owner);
weatherNft.updateSource(maliciousSource);
// Users have no way to detect this change or prevent it
// All subsequent weather updates will now return SUNNY regardless of actual conditions
// No timelock existed to warn users before the change
// No governance vote was required to approve the change
// No transparency mechanism alerts users to the modification
}

Recommended Mitigation

Considering all this, you can consider the following options:

1. On‑Chain Governance with Timelock

Implement OpenZeppelin’s Governor and TimelockController modules to enforce a delay and community voting
OpenZeppelin Docs
OpenZeppelin Docs
:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;
import "@openzeppelin/contracts/governance/TimelockController.sol";
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
contract WeatherNftTimelock is TimelockController {
constructor(address[] memory proposers, address[] memory executors)
TimelockController(2 days, proposers, executors) {}
}
contract WeatherNftGovernor is Governor, GovernorTimelockControl {
// Implement voting parameters, quorum, etc.
constructor(WeatherNftTimelock _timelock)
Governor("WeatherNftGovernor")
GovernorTimelockControl(_timelock) {}
// ...
}

Timelock Delay: Enforces a queue period (e.g., 48 hours) before execution, allowing users to exit if they disagree.

Community Proposals and Voting: Token holders can propose parameter updates and vote; only approved changes after the delay are executed.

2. Off‑Chain Voting & Transparency

Integrate an off‑chain voting UI via Snapshot or Aragon for low‑gas, user‑friendly governance

Snapshot: Gas‑less, supports custom strategies (e.g., NFT holdings, ERC‑20 weight)Link to the docs

Aragon: Provides both token‑based and multisig‑based governance modules, plus on‑chain execution options. Link to the official website

Emit explicit events in the contract for parameter updates, enabling front‑ends and block explorers to notify users of upcoming changes:

event SourceUpdated(string oldSource, string newSource);
event SubIdUpdated(uint64 oldSubId, uint64 newSubId);
event SecretsURLUpdated(bytes oldURL, bytes newURL);
Updates

Appeal created

bube Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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