Skip to content

Bug Bounty Submission: Same-Nonce Message Replay Vulnerability in Bridged Reputation Root Hash Update #1325

@loopghost

Description

@loopghost

Bug Bounty Submission: Same-Nonce Message Replay Vulnerability in Bridged Reputation Root Hash Update

Prerequisite

I ensured that this issue, specifically the weak nonce check (>=) in setReputationRootHashFromBridge allowing same-nonce replays, has not already been reported.

Summary

The setReputationRootHashFromBridge function within the ColonyNetworkMining.sol contract utilizes a non-strict nonce check (require(_nonce >= bridgeCurrentRootHashNonces[...])) for processing reputation root hash updates received via the bridge. This implementation flaw allows a message with a specific nonce to be processed multiple times consecutively if it is resubmitted before a message with a strictly higher nonce is processed. This enables a replay attack that forces the contract to re-execute logic, consume gas unnecessarily, and emit duplicate events, violating the integrity of the nonce mechanism and potentially impacting dependent off-chain systems. This constitutes a High Risk vulnerability according to the OWASP Risk Rating methodology.

Steps to Reproduce (Conceptual PoC)

This Proof of Concept demonstrates how a message with the same nonce can be processed multiple times. Let Chain M be the source chain and Chain C be the target chain where this code runs.

  • Initial State: Chain C has processed messages from Chain M up to nonce N. The state variable bridgeCurrentRootHashNonces[<Chain_M_ID>] on Chain C holds N. The reputation state is (HASH_OLD, LEAVES_OLD).

  • Valid Message Sent: Chain M sends Msg1 = (HASH_A, LEAVES_A, nonce=N+1) via the bridge to Chain C.

  • First Successful Processing on Chain C:

    • WormholeBridgeForColony calls ColonyNetworkMining.setReputationRootHashFromBridge(HASH_A, LEAVES_A, N+1).
    • Check: require(N+1 >= N) passes.
    • State updated to (HASH_A, LEAVES_A). Nonce map updated to N+1. Event ReputationRootHashSet(HASH_A, ...) emitted.
  • Replay Attempt: Before a message with nonce N+2 is sent/processed, an attacker resubmits the exact same Msg1 (containing nonce=N+1) to Chain C.

  • Second (Replay) Processing on Chain C:

    • WormholeBridgeForColony calls ColonyNetworkMining.setReputationRootHashFromBridge(HASH_A, LEAVES_A, N+1) again.
    • Check: require(nonce (N+1) >= bridgeCurrentRootHashNonces[<Chain_M_ID>] (N+1)) passes due to >=. <- Vulnerability.
    • State (HASH_A, LEAVES_A) is reapplied (no change). Nonce map set to N+1 (no change). Event ReputationRootHashSet(HASH_A, ...) is emitted again. Gas is consumed.

Expected Behavior

The nonce mechanism should strictly prevent the same message (identified by its nonce and origin) from being processed more than once. A check like require(_nonce > bridgeCurrentRootHashNonces[...]) should be used to ensure each nonce is processed at most once, rejecting replays of the exact same nonce.

Current Behaviour

The use of >= in the nonce check allows a message with nonce N+1 to be successfully processed even if the current stored nonce is already N+1, permitting consecutive replays.

Possible Solution

Modify the nonce check in ColonyNetworkMining.setReputationRootHashFromBridge to require the incoming nonce to be strictly greater than the last processed nonce:

// Inside setReputationRootHashFromBridge function
// Note: Assuming the map key is correctly representing the source chain ID in the actual implementation.
uint256 sourceChainId = ...; // Determine source chain ID correctly
uint256 lastProcessedNonce = bridgeCurrentRootHashNonces[sourceChainId];
require(_nonce > lastProcessedNonce, "colony-mining-bridge-nonce-must-be-greater");
bridgeCurrentRootHashNonces[sourceChainId] = _nonce;

Context

  • OWASP Risk Rating:

    • Likelihood: High. The flawed >= logic is present. Exploitation requires resubmitting a VAA, which is a feasible scenario for relayers or bridge mechanisms.
    • Impact: Medium. The replay does not corrupt the core state values but:
      • Weakens Nonce Integrity: Allows processing the same logical update multiple times.
      • Causes Unnecessary Gas Expenditure: Enables potential gas griefing on the target chain.
      • Generates Duplicate Events: Can disrupt off-chain indexers or systems relying on unique events per state update.
    • Overall OWASP Risk: High (Likelihood) * Medium (Impact) = High Risk.
  • Severity Classification: Based strictly on the OWASP Risk Rating methodology, a High Risk corresponds to a High Severity classification for this vulnerability.

Environment

  • Operating System: N/A (Blockchain/Solidity bug)
  • Ethereum client: N/A (Applies to any EVM chain where deployed)
  • solc version: 0.8.28 (as specified in pragmas)

Please consider rewarding this submission to your Bug Bounty Program accordingly as a High Severity vulnerability. Kindly issue the bounty to the following address: 0x36c81e0ec22cac063a0588b6165ce3fd022ab5b0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions