CVE-2021-41135 (Go, published 2021-10-20T18:15Z)
Description: value: The Cosmos-SDK is a framework for building blockchain applications in Golang. Affected versions of the SDK were vulnerable to a consensus halt due to non-deterministic behaviour in a ValidateBasic method in the x/authz module. The MsgGrant of the x/authz module contains a Grant field which includes a user-defined expiration time for when the authorization grant expires. In Grant.ValidateBasic(), that time is compared to the node’s local clock time. Any chain running an affected version of the SDK with the authz module enabled could be halted by anyone with the ability to send transactions on that chain. Recovery would require applying the patch and rolling back the latest block. Users are advised to update to version 0.44.2.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-754 \u2014 Improper Check for Unusual or Exceptional Conditions
The product does not check or incorrectly checks for unusual or exceptional conditions that are not expected to occur frequently during day to day operation of the product.
Repository: https://github.com/cosmos/cosmos-sdk
Files changed:
x/authz/authorization_grant.go
x/authz/authorization_grant_test.go
x/authz/client/testutil/tx.go
x/authz/keeper/msg_server.go
x/authz/msgs_test.go
Commit message: Merge pull request from GHSA-2p6r-37p9-89p2

* test: adding authz grant tests

* fix TestCLITxGrantAuthorization/Invalid_expiration_time test case

* comment out the test

* reenable test

Vulnerable code:
func NewGrant(a Authorization, expiration time.Time) (Grant, error) {
	if g.Expiration.Unix() < time.Now().Unix() {
		return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past")
	}

				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
			0,
			true,
// GrantAuthorization implements the MsgServer.Grant method.
		{"past time", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, false},

Fixed code:
func NewGrant( /*blockTime time.Time, */ a Authorization, expiration time.Time) (Grant, error) {
	// TODO: add this for 0.45
	// if !expiration.After(blockTime) {
	// 	return Grant{}, sdkerrors.ErrInvalidRequest.Wrapf("expiration must be after the current block time (%v), got %v", blockTime.Format(time.RFC3339), expiration.Format(time.RFC3339))
	// }
package authz

import (
	"testing"
	"time"

	// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
	"github.com/stretchr/testify/require"
)

func expecError(r *require.Assertions, expected string, received error) {
	if expected == "" {
		r.NoError(received)
	} else {
		r.Error(received)
		r.Contains(received.Error(), expected)
	}
}

func TestNewGrant(t *testing.T) {
	// ba := banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123)))
	a := NewGenericAuthorization("some-type")
	var tcs = []struct {
		title     string
		a         Authorization
		blockTime time.Time
		expire    time.Time
		err       string
	}{
		// {"wrong expire time (1)", a, time.Unix(10, 0), time.Unix(8, 0), "expiration must be after"},
		// {"wrong expire time (2)", a, time.Unix(10, 0), time.Unix(10, 0), "expiration must be after"},
		{"good expire time (1)", a, time.Unix(10, 0), time.Unix(10, 1), ""},
		{"good expire time (2)", a, time.Unix(10, 0), time.Unix(11, 0), ""},
	}

	for _, tc := range tcs {
		t.Run(tc.title, func(t *testing.T) {
			// _, err := NewGrant(tc.blockTime, tc.a, tc.expire)
			_, err := NewGrant(tc.a, tc.expire)
			expecError(require.New(t), tc.err, err)
		})
	}

}
				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
			0xd,
			false, // TODO: enable in v0.45
// GrantAuthorization implements the MsgServer.Grant method to create a new grant.
		{"past time", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, true}, // TODO need 0.45