CVE-2022-31121 (Go, published 2022-07-07T18:15Z)
Description: value: Hyperledger Fabric is a permissioned distributed ledger framework. In affected versions if a consensus client sends a malformed consensus request to an orderer it may crash the orderer node. A fix has been added in commit 0f1835949 which checks for missing consensus messages and returns an error to the consensus client should the message be missing. Users are advised to upgrade to versions 2.2.7 or v2.4.5. There are no known workarounds for this issue.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-20 \u2014 Improper Input Validation
The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Repository: https://github.com/hyperledger/fabric
Files changed:
orderer/common/cluster/comm_test.go
orderer/common/cluster/service.go
Commit message: Check if inner consensus message is missing

Change-Id: I06b466e6ff6d43f2b9804dd21185241716356050
Signed-off-by: Yacov Manevich <yacovm@il.ibm.com>
(cherry picked from commit 6e5e693a2d12aabee4bcf103ab7de3df4ccc49f9)


Vulnerable code:
	orderer.RegisterClusterServer(gRPCServer.Server(), cn)
	orderer.RegisterClusterServer(gRPCServer.Server(), tstSrv)
	// Else, it's a consensus message.
	return s.Dispatcher.DispatchConsensus(stream.Context(), request.GetConsensusRequest())

Fixed code:
type clusterServer interface {
	// Step passes an implementation-specific message to another cluster member.
	Step(server orderer.Cluster_StepServer) error
}

	dispatcher   clusterServer
	orderer.RegisterClusterServer(gRPCServer.Server(), cn.dispatcher)
	if tstSrv.dispatcher == nil {
		tstSrv.dispatcher = tstSrv
	}

	orderer.RegisterClusterServer(gRPCServer.Server(), tstSrv.dispatcher)
func TestEmptyRequest(t *testing.T) {
	// Scenario: Ensures empty messages are discarded and an error is returned
	// back to the sender.

	node1 := newTestNode(t)
	node2 := newTestNode(t)

	node2.srv.Stop()
	svc := &cluster.Service{
		StepLogger: flogging.MustGetLogger("test"),
		Logger:     flogging.MustGetLogger("test"),
		StreamCountReporter: &cluster.StreamCountReporter{
			Metrics: cluster.NewMetrics(&disabled.Provider{}),
		},
		Dispatcher: node2.c,
	}
	node2.dispatcher = svc

	// Sleep to let the gRPC service be closed
	time.Sleep(time.Second)

	// Resurrect the node with the new dispatcher
	node2.resurrect()

	defer node1.stop()
	defer node2.stop()

	config := []cluster.RemoteNode{node1.nodeInfo, node2.nodeInfo}
	node1.c.Configure(testChannel, config)
	node2.c.Configure(testChannel, config)

	assertBiDiCommunication(t, node1, node2, testReq)

	rm, err := node1.c.Remote(testChannel, node2.nodeInfo.ID)
	require.NoError(t, err)

	stream, err := rm.NewStream(time.Second * 10)
	require.NoError(t, err)

	err = stream.Send(&orderer.StepRequest{})
	require.NoError(t, err)

	_, err = stream.Recv()
	require.Error(t, err, "message is neither a Submit nor a Consensus request")
}

	"github.com/pkg/errors"
	} else if consensusReq := request.GetConsensusRequest(); consensusReq != nil {
		return s.Dispatcher.DispatchConsensus(stream.Context(), request.GetConsensusRequest())
	return errors.Errorf("message is neither a Submit nor a Consensus request")