Skip to content

Latest commit

 

History

History
100 lines (64 loc) · 6.13 KB

058.md

File metadata and controls

100 lines (64 loc) · 6.13 KB

Great Aegean Turkey

Medium

Epoching Module register errors with an error code of 1 which could lead to chain halt.

Summary

Epoching module register errors with an error code of 1 in error.go.

NOTE: Although a similar report was insufficiently brought up earlier for this contest here. The report was marked invalid and not fixed because it failed to identify any high or medium severity impact. Also, it lacks an attack/vulnerability path. So the report referenced above is not a finding.

However, this problem still exist in the current scope and could lead to chain halt. I'm reporting this because the first submission was insufficient and invalid(no H/M impact) according to Sherlock rules while this report provides a medium severity impact, describes the problem sufficiently, shows an attack path and should be fixed by protocol.

It's clearly stated in the Cosmos SDK Errors documentation, the error code :

Must be greater than one, as a code value of one is reserved for internal errors.

This breaks that rule.

But as seen on the Babylon's error.go implementation in the epoching module, an error code of 1 is used.

var (
	ErrUnwrappedMsgType = errorsmod.Register(ModuleName, 1, `       // @>> audit - code of 1 - wrong@@
										invalid message type in {MsgCreateValidator, MsgDelegate, MsgUndelegate, MsgBeginRedelegate, MsgCancelUnbondingDelegation, MsgEditValidator, MsgStakingUpdateParams}
										messages. For creating a validator use the wrapped version under 'tx checkpointing create-validator'
										and for the other messages use the wrapped versions under 'tx epoching {delegate,undelegate,redelegate,cancel-unbond}'`)
	ErrInvalidQueuedMessageType  = errorsmod.Register(ModuleName, 2, "invalid message type of a QueuedMessage")
	ErrUnknownEpochNumber        = errorsmod.Register(ModuleName, 3, "the epoch number is not known in DB")
	ErrUnknownSlashedVotingPower = errorsmod.Register(ModuleName, 5, "the slashed voting power is not known in DB. Maybe the epoch has been checkpointed?")
	ErrUnknownValidator          = errorsmod.Register(ModuleName, 6, "the validator is not known in the validator set.")
	ErrUnknownTotalVotingPower   = errorsmod.Register(ModuleName, 7, "the total voting power is not known in DB.")
	ErrMarshal                   = errorsmod.Register(ModuleName, 8, "marshal error.")
	ErrUnmarshal                 = errorsmod.Register(ModuleName, 9, "unmarshal error.")
	ErrNoWrappedMsg              = errorsmod.Register(ModuleName, 10, "the wrapped msg contains no msg inside.")
	ErrZeroEpochMsg              = errorsmod.Register(ModuleName, 11, "the 0-th epoch does not handle messages")
	ErrInvalidEpoch              = errorsmod.Register(ModuleName, 12, "the epoch is invalid")
	ErrInvalidHeight             = errorsmod.Register(ModuleName, 13, "the height is invalid")
	ErrInsufficientBalance       = errorsmod.Register(ModuleName, 14, "the delegator has insufficient balance to perform delegate")

The Cosmos SDK reserves error code 1 for internal errors. Therefore, if an error code of 1 is returned when it is not an internal error, the SDK might interpret it as an internal SDK error rather than a custom error from your application. What does this mean? The SDK could treat this as a critical failure and halt further processing of the transaction or block. This means that this issue could lead to a chain halt. This is because if the SDK encounters error code 1, it could assume that the state transition failed due to an internal issue and trigger a rollback or halt the chain to prevent further corruption

A similar valid report was made during the Allora's contest. Here

Root Cause

In errors.go:9-13, code of 1 used to register an error.

var (
	ErrUnwrappedMsgType = errorsmod.Register(ModuleName, 1, `
										invalid message type in {MsgCreateValidator, MsgDelegate, MsgUndelegate, MsgBeginRedelegate, MsgCancelUnbondingDelegation, MsgEditValidator, MsgStakingUpdateParams}
										messages. For creating a validator use the wrapped version under 'tx checkpointing create-validator'
										and for the other messages use the wrapped versions under 'tx epoching {delegate,undelegate,redelegate,cancel-unbond}'`)

Internal Pre-conditions

Epoching module register errors with an error code of 1 in error.go

External Pre-conditions

An error related to invalid message type and the other errors registered with a code value of 1 occurs.

Attack Path

  1. An attacker crafts a transaction or message that triggers the custom error (ErrUnwrappedMsgType) or other related errors.

  2. The error is being misinterpreted as it as an internal SDK error rather than a custom error from the protocol.

  3. This triggers a Rollback or Halt. It may rollback the transaction, halt the chain or crash the node If the error is unhandled.

  4. In any case, this disrupts the chain and makes it behave in an unexpected way. If the SDK halts the chain or crashes the node, the network experiences downtime.

Consequently, validators and nodes stop producing blocks. Users are unable to send transactions or interact with the chain.

If the SDK rolls back the transaction, the attacker can repeatedly trigger the error to disrupt normal chain operations.

Impact

  1. It violates a fundamental rule of the Cosmos SDK (error codes must be greater than 1).

  2. It can lead to chain halts, state corruption, or node crashes when the error is being misinterpreted to be an internal SDK error .

  3. It can cause ambiguity in error handling, making it difficult to debug and resolve issues.

PoC

https://docs.cosmos.network/main/build/building-modules/errors#registration

https://github.com/sherlock-audit/2024-12-babylon/blob/main/babylon/x/epoching/types/errors.go#L9-L13

Mitigation

Do not use error code of 1. It is advised to start from 2.