code-423n4 / 2024-05-canto-findings

0 stars 0 forks source link

Incomplete "cosmos.msg.v1.signer" protobuf annotation causes the "MsgSwapOrder" message to fail #4

Closed c4-bot-6 closed 4 months ago

c4-bot-6 commented 4 months ago

Lines of code

https://github.com/code-423n4/2024-05-canto/blob/d1d51b2293d4689f467b8b1c82bba84f8f7ea008/canto-main/proto/canto/coinswap/v1/tx.proto#L97

Vulnerability details

Before Cosmos SDK v0.50, the GetSigners method was used to specify what addresses are required to sign a transactional message. With Cosmos SDK v0.50 this method has been dropped and replaced with the declarative cosmos.msg.v1.signer protobuf tag.

This tag was applied by the team correctly in most places, however, for MsgSwapOrder, the annotation points to a nested Input message, which however does not have a cosmos.msg.v1.signer to resolve the signer indirectly:

message MsgSwapOrder {
  option (cosmos.msg.v1.signer) = "input";
  option (amino.name) = "canto/MsgSwapOrder";

  Input input = 1 [ (gogoproto.nullable) = false ];
  Output output = 2 [ (gogoproto.nullable) = false ];
  int64 deadline = 3;
  bool is_buy_order = 4 [ (gogoproto.moretags) = "yaml:\"is_buy_order\"" ];
}
message Input {
  string address = 1;
  cosmos.base.v1beta1.Coin coin = 2 [ (gogoproto.nullable) = false ];
}

Impact

The messages MsgSwapOrder will always fail on the Canto node.

Proof of Concept

The issue can be verified by adding the following test in the app folder:

canto-main/app/signers_test.go ```go package app import ( "cosmossdk.io/x/tx/signing" coinswapapi "github.com/Canto-Network/Canto/v7/api/canto/coinswap/v1" "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" ) func TestMsgSwapOrderSigners(t *testing.T) { sw := coinswapapi.MsgSwapOrder{ Input: &coinswapapi.Input{Address: "something"}, } ctx, err := signing.NewContext(signing.Options{ AddressCodec: address.Bech32Codec{ Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(), }, ValidatorAddressCodec: address.Bech32Codec{ Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(), }, }) require.NoError(t, err) signers, err := ctx.GetSigners(&sw) require.NoError(t, err) assert.Equal(t, 1, len(signers)) assert.Equal(t, "something", signers[0]) } ```

Its output is:

no cosmos.msg.v1.signer option found for message canto.coinswap.v1.Input; use DefineCustomGetSigners to specify a custom getter

Tools Used

Code review

Recommended Mitigation Steps

Consider adding a DefineCustomGetSigners call in app.go for the x/coinswap module's Input message, as done for MsgConvertERC20.

Alternatively, consider adding a cosmos.msg.v1.signer tag to the x/coinswap module's Input message, pointing to its address field.

Assessed type

Invalid Validation

thebrittfactor commented 4 months ago

Warden will be acting as the judge for this audit and therefore, has agreed to forfeit their submissions and will not be eligible for awards for this audit.

C4-Staff commented 4 months ago

CloudEllie marked the issue as duplicate of #27

c4-judge commented 4 months ago

3docSec marked the issue as satisfactory