Skip to content

Commit

Permalink
Merge branch 'main' into chore/go-version
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth authored Sep 14, 2024
2 parents 1329db4 + c53e132 commit 86e109b
Show file tree
Hide file tree
Showing 18 changed files with 760 additions and 160 deletions.
75 changes: 75 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Security Policy

## Introduction

Security researchers are essential in identifying vulnerabilities that may impact the Axelar Network. If you have discovered a security vulnerability in the Axelar chain or any repository managed by Axelar, we encourage you to notify us using one of the methods outlined below.

### Guidelines for Responsible Vulnerability Testing and Reporting

1. **Refrain from testing vulnerabilities on our publicly accessible environments**, including but not limited to:
- Axelar mainnet
- Axelar Frontend Apps e.g satellite.money
- Axelar Testnet
- Axelar Testnet Frontend Apps e.g testnet.satellite.money

2. **Avoid reporting security vulnerabilities through public channels, including GitHub issues**

## Reporting Security Issues

To privately report a security vulnerability, please choose one of the following options:

### 1. Email

Send your detailed vulnerability report to `[email protected]`.

### 2. Bug Bounty Program

Axelar is partnered with Immunefi to offer a bug bounty program. Please visit [Immunefi's website](https://immunefi.com/bug-bounty/axelarnetwork/information/) for more information.

## Submit Vulnerability Report

When reporting a vulnerability through either method, please include the following details to aid in our assessment:

- Type of vulnerability
- Description of the vulnerability
- Steps to reproduce the issue
- Impact of the issue
- Explanation of how an attacker could exploit it

> [!NOTE]
> Review our criteria in the [Official Docs](https://docs.axelar.dev/resources/bug-bounty/#vulnerability-criteria)
## Vulnerability Disclosure Process

1. **Initial Report**: Submit the vulnerability via one of the above channels.
2. **Confirmation**: We will confirm receipt of your report within 48 hours.
3. **Assessment**: Our security team will evaluate the vulnerability and inform you of its severity and the estimated time frame for resolution.
4. **Resolution**: Once fixed, you will be contacted to verify the solution.
5. **Public Disclosure**: Details of the vulnerability may be publicly disclosed after ensuring it poses no further risk.

During the vulnerability disclosure process, we ask security researchers to keep vulnerabilities and communications around vulnerability submissions private and confidential until a patch is developed. Should a security issue require a network upgrade, additional time may be needed to raise a governance proposal and complete the upgrade.

During this time:

- Avoid exploiting any vulnerabilities you discover.
- Demonstrate good faith by not disrupting or degrading Axelar's services.

## Severity Characterization

| Severity | Description |
|--------------|-------------------------------------------------------------------------|
| **CRITICAL** | Immediate threat to critical systems (e.g., chain halts, funds at risk) |
| **HIGH** | Significant impact on major functionality |
| **MEDIUM** | Impacts minor features or exposes non-sensitive data |
| **LOW** | Minimal impact |

## Bug Bounty

Our bug bounty program is managed by Immunefi. Please visit [Immunefi's website](https://immunefi.com/bug-bounty/axelarnetwork/information/) for more information.

> [!WARNING]
> Targeting our production environments will disqualify you from receiving any bounty.
## Feedback on this Policy

For recommendations on how to improve this policy, either submit a pull request or send an email to `[email protected]`.
31 changes: 20 additions & 11 deletions app/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/CosmWasm/wasmd/x/wasm"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server/types"
Expand Down Expand Up @@ -163,20 +164,28 @@ func initStakingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, ke

func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, bApp *bam.BaseApp, appOpts types.AppOptions, wasmOpts []wasm.Option, wasmDir string) *wasm.Keeper {
wasmConfig := mustReadWasmConfig(appOpts)
nexusK := GetKeeper[nexusKeeper.Keeper](keepers)

// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
wasmOpts = append(wasmOpts, wasmkeeper.WithMessageHandlerDecorator(
func(old wasmkeeper.Messenger) wasmkeeper.Messenger {
encoders := wasm.DefaultEncoders(encodingConfig.Codec, GetKeeper[ibctransferkeeper.Keeper](keepers))
encoders.Custom = nexusKeeper.EncodeRoutingMessage

return WithAnteHandlers(
encoders,
initMessageAnteDecorators(encodingConfig, keepers),
// for security reasons we disallow some msg types that can be used for arbitrary calls
wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(GetKeeper[nexusKeeper.Keeper](keepers))))
}))
wasmOpts = append(
wasmOpts,
wasmkeeper.WithMessageHandlerDecorator(
func(old wasmkeeper.Messenger) wasmkeeper.Messenger {
encoders := wasm.DefaultEncoders(encodingConfig.Codec, GetKeeper[ibctransferkeeper.Keeper](keepers))
encoders.Custom = nexusKeeper.EncodeRoutingMessage

return WithAnteHandlers(
encoders,
initMessageAnteDecorators(encodingConfig, keepers),
// for security reasons we disallow some msg types that can be used for arbitrary calls
wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(nexusK)))
}),
wasmkeeper.WithWasmEngineDecorator(func(old wasmtypes.WasmerEngine) wasmtypes.WasmerEngine {
return nexusKeeper.NewWasmerEngine(old, nexusK)
}),
wasmkeeper.WithQueryPlugins(NewQueryPlugins(nexusK)),
)

scopedWasmK := GetKeeper[capabilitykeeper.Keeper](keepers).ScopeToModule(wasm.ModuleName)
ibcKeeper := GetKeeper[ibckeeper.Keeper](keepers)
Expand Down
28 changes: 28 additions & 0 deletions app/wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import (
"golang.org/x/exp/maps"

"github.com/axelarnetwork/axelar-core/x/ante"
nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported"
nexusKeeper "github.com/axelarnetwork/axelar-core/x/nexus/keeper"
nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types"
"github.com/axelarnetwork/utils/funcs"
)

Expand Down Expand Up @@ -146,3 +149,28 @@ func (m WasmAppModuleBasicOverride) DefaultGenesis(cdc codec.JSONCodec) json.Raw
},
})
}

// QueryRequest is the custom queries wasm contracts can make for the core modules
type QueryRequest struct {
Nexus *nexus.WasmQueryRequest
}

// NewQueryPlugins returns a new instance of the custom query plugins
func NewQueryPlugins(msgIDGenerator nexustypes.MsgIDGenerator) *wasmkeeper.QueryPlugins {
nexusWasmQuerier := nexusKeeper.NewWasmQuerier(msgIDGenerator)

return &wasmkeeper.QueryPlugins{
Custom: func(ctx sdk.Context, request json.RawMessage) ([]byte, error) {
req := QueryRequest{}
if err := json.Unmarshal(request, &req); err != nil {
return nil, wasmvmtypes.InvalidRequest{Err: "invalid Custom query request", Request: request}
}

if req.Nexus != nil {
return nexusWasmQuerier.Query(ctx, *req.Nexus)
}

return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown Custom query request"}
},
}
}
62 changes: 62 additions & 0 deletions app/wasm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app_test

import (
"encoding/json"
"fmt"
"testing"

"github.com/CosmWasm/wasmd/x/wasm"
Expand All @@ -20,6 +21,8 @@ import (
"github.com/axelarnetwork/axelar-core/cmd/axelard/cmd"
"github.com/axelarnetwork/axelar-core/testutils/fake"
"github.com/axelarnetwork/axelar-core/testutils/rand"
nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/types/mock"
"github.com/axelarnetwork/utils/funcs"
. "github.com/axelarnetwork/utils/test"
)

Expand Down Expand Up @@ -328,3 +331,62 @@ func TestMaxSizeOverrideForClient(t *testing.T) {

assert.NoError(t, msg.ValidateBasic())
}

func TestQueryPlugins(t *testing.T) {
var (
msgIDGenerator *nexusmock.MsgIDGeneratorMock
req json.RawMessage
ctx sdk.Context
)

Given("the tx id generator", func() {
ctx = sdk.NewContext(nil, tmproto.Header{}, false, log.TestingLogger())
msgIDGenerator = &nexusmock.MsgIDGeneratorMock{}
}).
Branch(
When("request is invalid", func() {
req = []byte("{\"invalid\"}")
}).
Then("it should return an error", func(t *testing.T) {
_, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req)

assert.ErrorContains(t, err, "invalid Custom query request")
}),

When("request is unknown", func() {
req = []byte("{\"unknown\":{}}")
}).
Then("it should return an error", func(t *testing.T) {
_, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req)

assert.ErrorContains(t, err, "unknown Custom query request")
}),

When("request is a nexus wasm query but unknown", func() {
req = []byte("{\"nexus\":{}}")
}).
Then("it should return an error", func(t *testing.T) {
_, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req)

assert.ErrorContains(t, err, "unknown Nexus query request")
}),

When("request is a nexus wasm TxID query", func() {
req = []byte("{\"nexus\":{\"tx_hash_and_nonce\":{}}}")
}).
Then("it should return an error", func(t *testing.T) {
txHash := [32]byte(rand.Bytes(32))
index := uint64(rand.PosI64())
msgIDGenerator.CurrIDFunc = func(ctx sdk.Context) ([32]byte, uint64) {
return txHash, index
}

actual, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req)

assert.NoError(t, err)
assert.Equal(t, fmt.Sprintf("{\"tx_hash\":%s,\"nonce\":%d}", funcs.Must(json.Marshal(txHash)), index), string(actual))
}),
).
Run(t)

}
1 change: 1 addition & 0 deletions docs/proto/proto-docs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions proto/axelar/nexus/exported/v1beta1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ message WasmMessage {
uint64 source_tx_index = 7 [ (gogoproto.jsontag) = "source_tx_index" ];
bytes sender = 8 [ (gogoproto.casttype) =
"github.com/cosmos/cosmos-sdk/types.AccAddress" ];
string id = 9 [
(gogoproto.customname) = "ID"
];
string id = 9 [ (gogoproto.customname) = "ID" ];
cosmos.base.v1beta1.Coin token = 10
[ (gogoproto.nullable) = true, (gogoproto.customname) = "Asset" ];
}
2 changes: 1 addition & 1 deletion testutils/fake/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (n *Node) start() {
if err != nil {
n.Ctx.Logger().Error(fmt.Sprintf("error from handler for route %s: %s", msgRoute, err.Error()))
// to allow failed messages we need to implement a cache for the multistore to revert in case of failure
// outputing the error message here so that we can have a sense for why it panics in case verbose mode is not active.
// outputting the error message here so that we can have a sense for why it panics in case verbose mode is not active.
panic(fmt.Sprintf("no failing messages allowed for now: error from handler for route %s: %s\nmessage: %v", msgRoute, err.Error(), msg))
}
msgEvents := sdk.Events{
Expand Down
2 changes: 1 addition & 1 deletion testutils/fake/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type MultiStore struct {
*mock.MultiStoreMock
}

// CachedMultiStore is a simple chached multistore for testing
// CachedMultiStore is a simple cached multistore for testing
type CachedMultiStore struct {
kvstore map[string]interfaces.KVStore
*mock.CacheMultiStoreMock
Expand Down
11 changes: 11 additions & 0 deletions x/nexus/exported/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,14 @@ func (bz *WasmBytes) UnmarshalJSON(data []byte) error {

return nil
}

// WasmQueryRequest is the request for wasm contracts to query
type WasmQueryRequest struct {
TxHashAndNonce *struct{} `json:"tx_hash_and_nonce,omitempty"`
}

// WasmQueryTxHashAndNonceResponse is the response for the TxHashAndNonce query
type WasmQueryTxHashAndNonceResponse struct {
TxHash [32]byte `json:"tx_hash,omitempty"` // the hash of the current transaction
Nonce uint64 `json:"nonce,omitempty"` // the nonce of the current execution, which increments with each entry of any wasm execution
}
Loading

0 comments on commit 86e109b

Please sign in to comment.