Skip to content

Commit bbf020f

Browse files
authored
fix: Prevent signing from wrong key in multisig (#12548)
1 parent 63d484a commit bbf020f

File tree

3 files changed

+51
-10
lines changed

3 files changed

+51
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
8282

8383
### Bug Fixes
8484

85+
* [#12548](https://github.com/cosmos/cosmos-sdk/pull/12548) Prevent signing from wrong key while using multisig.
8586
* [#12416](https://github.com/cosmos/cosmos-sdk/pull/12416) Prevent zero gas transactions in the `DeductFeeDecorator` AnteHandler decorator.
8687
* (x/mint) [#12384](https://github.com/cosmos/cosmos-sdk/pull/12384) Ensure `GoalBonded` must be positive when performing `x/mint` parameter validation.
8788
* (x/auth) [#12261](https://github.com/cosmos/cosmos-sdk/pull/12261) Deprecate pagination in GetTxsEventRequest/Response in favor of page and limit to align with tendermint `SignClient.TxSearch`

x/auth/client/cli/tx_sign.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import (
99
"github.com/cosmos/cosmos-sdk/client"
1010
"github.com/cosmos/cosmos-sdk/client/flags"
1111
"github.com/cosmos/cosmos-sdk/client/tx"
12-
sdk "github.com/cosmos/cosmos-sdk/types"
12+
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
13+
1314
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
1415
)
1516

@@ -224,7 +225,6 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
224225
return err
225226
}
226227

227-
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
228228
txCfg := clientCtx.TxConfig
229229
txBuilder, err := txCfg.WrapTxBuilder(newTx)
230230
if err != nil {
@@ -244,14 +244,39 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
244244

245245
overwrite, _ := f.GetBool(flagOverwrite)
246246
if multisig != "" {
247-
multisigAddr, err := sdk.AccAddressFromBech32(multisig)
247+
// Bech32 decode error, maybe it's a name, we try to fetch from keyring
248+
multisigAddr, multisigName, _, err := client.GetFromFields(clientCtx, txF.Keybase(), multisig)
248249
if err != nil {
249-
// Bech32 decode error, maybe it's a name, we try to fetch from keyring
250-
multisigAddr, _, _, err = client.GetFromFields(clientCtx, txFactory.Keybase(), multisig)
251-
if err != nil {
252-
return fmt.Errorf("error getting account from keybase: %w", err)
250+
return fmt.Errorf("error getting account from keybase: %w", err)
251+
}
252+
multisigkey, err := getMultisigRecord(clientCtx, multisigName)
253+
if err != nil {
254+
return err
255+
}
256+
multisigPubKey, err := multisigkey.GetPubKey()
257+
if err != nil {
258+
return err
259+
}
260+
multisigLegacyPub := multisigPubKey.(*kmultisig.LegacyAminoPubKey)
261+
262+
fromRecord, err := clientCtx.Keyring.Key(fromName)
263+
if err != nil {
264+
return fmt.Errorf("error getting account from keybase: %w", err)
265+
}
266+
fromPubKey, err := fromRecord.GetPubKey()
267+
if err != nil {
268+
return err
269+
}
270+
271+
var found bool
272+
for _, pubkey := range multisigLegacyPub.GetPubKeys() {
273+
if pubkey.Equals(fromPubKey) {
274+
found = true
253275
}
254276
}
277+
if !found {
278+
return fmt.Errorf("signing key is not a part of multisig key")
279+
}
255280
err = authclient.SignTxWithSignerAddress(
256281
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline, overwrite)
257282
if err != nil {

x/auth/client/testutil/suite.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ func (s *IntegrationTestSuite) SetupSuite() {
7474
pub2, err := account2.GetPubKey()
7575
s.Require().NoError(err)
7676

77+
// Create a dummy account for testing purpose
78+
_, _, err = kb.NewMnemonic("dummyAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
79+
s.Require().NoError(err)
80+
7781
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pub1, pub2})
7882
_, err = kb.SaveMultisig("multi", multi)
7983
s.Require().NoError(err)
@@ -938,6 +942,10 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
938942
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi")
939943
s.Require().NoError(err)
940944

945+
// Generate dummy account which is not a part of multisig.
946+
dummyAcc, err := val1.ClientCtx.Keyring.Key("dummyAccount")
947+
s.Require().NoError(err)
948+
941949
addr, err := multisigRecord.GetAddress()
942950
s.Require().NoError(err)
943951
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, addr)
@@ -995,14 +1003,21 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
9951003

9961004
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
9971005

998-
// Sign with account1
1006+
// Sign with account2
9991007
addr2, err := account2.GetAddress()
10001008
s.Require().NoError(err)
10011009
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String())
10021010
s.Require().NoError(err)
10031011

10041012
sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
10051013

1014+
// Sign with dummy account
1015+
dummyAddr, err := dummyAcc.GetAddress()
1016+
s.Require().NoError(err)
1017+
_, err = TxSignExec(val1.ClientCtx, dummyAddr, multiGeneratedTxFile.Name(), "--multisig", addr.String())
1018+
s.Require().Error(err)
1019+
s.Require().Contains(err.Error(), "signing key is not a part of multisig key")
1020+
10061021
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
10071022
s.Require().NoError(err)
10081023

@@ -1057,7 +1072,7 @@ func (s *IntegrationTestSuite) TestSignWithMultisig() {
10571072
// as the main point of this test is to test the `--multisig` flag with an address
10581073
// that is not in the keyring.
10591074
_, err = TxSignExec(val1.ClientCtx, addr1, multiGeneratedTx2File.Name(), "--multisig", multisigAddr.String())
1060-
s.Require().Contains(err.Error(), "tx intended signer does not match the given signer")
1075+
s.Require().Contains(err.Error(), "error getting account from keybase")
10611076
}
10621077

10631078
func (s *IntegrationTestSuite) TestCLIMultisign() {
@@ -1124,7 +1139,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
11241139

11251140
addr2, err := account2.GetAddress()
11261141
s.Require().NoError(err)
1127-
// Sign with account1
1142+
// Sign with account2
11281143
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String())
11291144
s.Require().NoError(err)
11301145

0 commit comments

Comments
 (0)