From 8776a6a4d77d3d4ff0da25ce009595d78d6e8d21 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Mon, 28 Oct 2024 15:00:52 -0700 Subject: [PATCH] chore: update gosec (#2933) * chore: update gosec * Address gosec errors * update * fix spelling * disable sumdb in rpcimportable test to fix: reading https://sum.golang.org/lookup/github.com/zeta-chain/node@v0.0.0-20241028213324-8a6a543615d0: 500 Internal Server Error --- .github/workflows/ci.yml | 3 +- .github/workflows/sast-linters.yml | 2 +- cmd/zetaclientd/p2p_diagnostics.go | 1 + e2e/e2etests/test_bitcoin_std_deposit.go | 2 ++ e2e/runner/setup_solana.go | 3 +- pkg/contracts/ton/gateway.go | 1 + pkg/crypto/aes256_gcm.go | 1 + pkg/memo/codec_compact.go | 1 + pkg/ticker/ticker.go | 7 ++-- precompiles/logs/logs.go | 7 ++-- precompiles/staking/staking.go | 5 +-- rpc/backend/node_info.go | 4 ++- rpc/backend/tx_info.go | 6 ++-- rpc/namespaces/ethereum/debug/api.go | 8 +++++ rpc/types/utils.go | 32 +++++++++++-------- scripts/gosec.sh | 2 +- zetaclient/chains/bitcoin/observer/inbound.go | 1 + zetaclient/chains/evm/observer/inbound.go | 4 +-- zetaclient/chains/evm/observer/outbound.go | 1 + zetaclient/chains/ton/observer/inbound.go | 4 +-- zetaclient/orchestrator/orchestrator.go | 2 +- zetaclient/types/dynamic_ticker.go | 4 ++- zetaclient/zetacore/client_worker.go | 1 + 23 files changed, 67 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 518823b42f..741931df27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,8 +105,9 @@ jobs: - name: go get node working-directory: contrib/rpcimportable run: go get github.com/zeta-chain/node@${{github.event.pull_request.head.sha || github.sha}} - env: + env: GOPROXY: direct + GOSUMDB: off - name: go mod tidy working-directory: contrib/rpcimportable run: go mod tidy diff --git a/.github/workflows/sast-linters.yml b/.github/workflows/sast-linters.yml index 26c8fb895d..7b09472298 100644 --- a/.github/workflows/sast-linters.yml +++ b/.github/workflows/sast-linters.yml @@ -25,7 +25,7 @@ jobs: fetch-depth: 0 - name: Run Gosec Security Scanner - uses: zeta-chain/gosec@v2.21.0-zeta + uses: zeta-chain/gosec@v2.21.4-zeta2 with: args: -exclude-generated -exclude-dir testutil ./... diff --git a/cmd/zetaclientd/p2p_diagnostics.go b/cmd/zetaclientd/p2p_diagnostics.go index 201b91504b..b041c4993b 100644 --- a/cmd/zetaclientd/p2p_diagnostics.go +++ b/cmd/zetaclientd/p2p_diagnostics.go @@ -151,6 +151,7 @@ func RunDiagnostics( startLogger.Info().Msgf("Successfully announced!") // every 1min, print out the p2p diagnostic + // #nosec G115 interval is in range and not user controlled ticker := time.NewTicker(time.Duration(cfg.P2PDiagnosticTicker) * time.Second) round := 0 diff --git a/e2e/e2etests/test_bitcoin_std_deposit.go b/e2e/e2etests/test_bitcoin_std_deposit.go index fa123b94cd..e90b23d64a 100644 --- a/e2e/e2etests/test_bitcoin_std_deposit.go +++ b/e2e/e2etests/test_bitcoin_std_deposit.go @@ -59,5 +59,7 @@ func TestBitcoinStdMemoDeposit(r *runner.E2ERunner, args []string) { amountIncreased := new(big.Int).Sub(balanceAfter, balanceBefore) amountSatoshis, err := bitcoin.GetSatoshis(amount) require.NoError(r, err) + require.Positive(r, amountSatoshis) + // #nosec G115 always positive require.Equal(r, uint64(amountSatoshis), amountIncreased.Uint64()) } diff --git a/e2e/runner/setup_solana.go b/e2e/runner/setup_solana.go index 17bf3149dd..b8bb309ba1 100644 --- a/e2e/runner/setup_solana.go +++ b/e2e/runner/setup_solana.go @@ -56,7 +56,8 @@ func (r *E2ERunner) SetupSolana(deployerPrivateKey string) { inst.DataBytes, err = borsh.Serialize(solanacontracts.InitializeParams{ Discriminator: solanacontracts.DiscriminatorInitialize(), TssAddress: r.TSSAddress, - ChainID: uint64(chains.SolanaLocalnet.ChainId), + // #nosec G115 chain id always positive + ChainID: uint64(chains.SolanaLocalnet.ChainId), }) require.NoError(r, err) diff --git a/pkg/contracts/ton/gateway.go b/pkg/contracts/ton/gateway.go index 33ca2c7977..ab21a41ba3 100644 --- a/pkg/contracts/ton/gateway.go +++ b/pkg/contracts/ton/gateway.go @@ -124,6 +124,7 @@ func (gw *Gateway) parseInbound(tx ton.Transaction) (*Transaction, error) { var ( sender = *sourceID + // #nosec G115 always in range opCode = Op(op) content any diff --git a/pkg/crypto/aes256_gcm.go b/pkg/crypto/aes256_gcm.go index e4fba7de7c..a7538363da 100644 --- a/pkg/crypto/aes256_gcm.go +++ b/pkg/crypto/aes256_gcm.go @@ -103,6 +103,7 @@ func DecryptAES256GCM(ciphertext []byte, password string) ([]byte, error) { nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] // decrypt the ciphertext + // #nosec G407 false positive https://github.com/securego/gosec/issues/1211 plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { return nil, err diff --git a/pkg/memo/codec_compact.go b/pkg/memo/codec_compact.go index bcb49d3f92..817a12066a 100644 --- a/pkg/memo/codec_compact.go +++ b/pkg/memo/codec_compact.go @@ -120,6 +120,7 @@ func (c *CodecCompact) packLength(length int) ([]byte, error) { if length > math.MaxUint8 { return nil, fmt.Errorf("data length %d exceeds %d bytes", length, math.MaxUint8) } + // #nosec G115 range checked data[0] = uint8(length) case LenBytesLong: if length > math.MaxUint16 { diff --git a/pkg/ticker/ticker.go b/pkg/ticker/ticker.go index 2a5a7edff1..94d4a87efc 100644 --- a/pkg/ticker/ticker.go +++ b/pkg/ticker/ticker.go @@ -183,7 +183,8 @@ func (t *Ticker) Stop() { t.logger.Info().Msgf("Ticker stopped") } -// SecondsFromUint64 converts uint64 to time.Duration in seconds. -func SecondsFromUint64(d uint64) time.Duration { - return time.Duration(d) * time.Second +// DurationFromUint64Seconds converts uint64 of seconds to time.Duration. +func DurationFromUint64Seconds(seconds uint64) time.Duration { + // #nosec G115 seconds should be in range and is not user controlled + return time.Duration(seconds) * time.Second } diff --git a/precompiles/logs/logs.go b/precompiles/logs/logs.go index 07960a442e..6848cbc9a0 100644 --- a/precompiles/logs/logs.go +++ b/precompiles/logs/logs.go @@ -16,9 +16,10 @@ type Argument struct { // AddLog adds log to stateDB func AddLog(ctx sdk.Context, precompileAddr common.Address, stateDB vm.StateDB, topics []common.Hash, data []byte) { stateDB.AddLog(&types.Log{ - Address: precompileAddr, - Topics: topics, - Data: data, + Address: precompileAddr, + Topics: topics, + Data: data, + // #nosec G115 block height always positive BlockNumber: uint64(ctx.BlockHeight()), }) } diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index fea0d0f9f2..d29082e545 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -133,8 +133,9 @@ func (c *Contract) GetAllValidators( validatorsRes[i] = Validator{ OperatorAddress: v.OperatorAddress, ConsensusPubKey: v.ConsensusPubkey.String(), - BondStatus: uint8(v.Status), - Jailed: v.Jailed, + // #nosec G115 enum always in range + BondStatus: uint8(v.Status), + Jailed: v.Jailed, } } diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index 0a5c9c0b0b..180389298e 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -81,8 +81,10 @@ func (b *Backend) Syncing() (interface{}, error) { } return map[string]interface{}{ + // #nosec G115 block height always positive "startingBlock": hexutil.Uint64(status.SyncInfo.EarliestBlockHeight), - "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), + // #nosec G115 block height always positive + "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), // "highestBlock": nil, // NA // "pulledStates": nil, // NA // "knownStates": nil, // NA diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 3d2810331d..3f69ec86f9 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -304,8 +304,10 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ // Inclusion information: These fields provide information about the inclusion of the // transaction corresponding to this receipt. - "blockHash": common.BytesToHash(resBlock.Block.Header.Hash()).Hex(), - "blockNumber": hexutil.Uint64(res.Height), + "blockHash": common.BytesToHash(resBlock.Block.Header.Hash()).Hex(), + // #nosec G115 height always positive + "blockNumber": hexutil.Uint64(res.Height), + // #nosec G115 tx index always positive "transactionIndex": hexutil.Uint64(res.EthTxIndex), // sender and receiver (contract or EOA) addreses diff --git a/rpc/namespaces/ethereum/debug/api.go b/rpc/namespaces/ethereum/debug/api.go index 27c4ec5500..39288a125f 100644 --- a/rpc/namespaces/ethereum/debug/api.go +++ b/rpc/namespaces/ethereum/debug/api.go @@ -126,6 +126,7 @@ func (a *API) BlockProfile(file string, nsec uint) error { runtime.SetBlockProfileRate(1) defer runtime.SetBlockProfileRate(0) + // #nosec G115 uint always in int64 range time.Sleep(time.Duration(nsec) * time.Second) return writeProfile("block", file, a.logger) } @@ -137,6 +138,7 @@ func (a *API) CpuProfile(file string, nsec uint) error { //nolint: golint, style if err := a.StartCPUProfile(file); err != nil { return err } + // #nosec G115 uint always in int64 range time.Sleep(time.Duration(nsec) * time.Second) return a.StopCPUProfile() } @@ -156,6 +158,7 @@ func (a *API) GoTrace(file string, nsec uint) error { if err := a.StartGoTrace(file); err != nil { return err } + // #nosec G115 uint always in int64 range time.Sleep(time.Duration(nsec) * time.Second) return a.StopGoTrace() } @@ -273,6 +276,7 @@ func (a *API) WriteMemProfile(file string) error { func (a *API) MutexProfile(file string, nsec uint) error { a.logger.Debug("debug_mutexProfile", "file", file, "nsec", nsec) runtime.SetMutexProfileFraction(1) + // #nosec G115 uint always in int64 range time.Sleep(time.Duration(nsec) * time.Second) defer runtime.SetMutexProfileFraction(0) return writeProfile("mutex", file, a.logger) @@ -305,6 +309,7 @@ func (a *API) SetGCPercent(v int) int { // GetHeaderRlp retrieves the RLP encoded for of a single header. func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { + // #nosec G115 number always in int64 range header, err := a.backend.HeaderByNumber(rpctypes.BlockNumber(number)) if err != nil { return nil, err @@ -315,6 +320,7 @@ func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { // GetBlockRlp retrieves the RLP encoded for of a single block. func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { + // #nosec G115 number always in int64 range block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) if err != nil { return nil, err @@ -325,6 +331,7 @@ func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { // PrintBlock retrieves a block and returns its pretty printed form. func (a *API) PrintBlock(number uint64) (string, error) { + // #nosec G115 number always in int64 range block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) if err != nil { return "", err @@ -335,6 +342,7 @@ func (a *API) PrintBlock(number uint64) (string, error) { // SeedHash retrieves the seed hash of a block. func (a *API) SeedHash(number uint64) (string, error) { + // #nosec G115 number always in int64 range _, err := a.backend.HeaderByNumber(rpctypes.BlockNumber(number)) if err != nil { return "", err diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 67ee50133a..a17f3af2a2 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -133,20 +133,24 @@ func FormatBlock( } result := map[string]interface{}{ - "number": hexutil.Uint64(header.Height), - "hash": hexutil.Bytes(header.Hash()), - "parentHash": common.BytesToHash(header.LastBlockID.Hash.Bytes()), - "nonce": ethtypes.BlockNonce{}, // PoW specific - "sha3Uncles": ethtypes.EmptyUncleHash, // No uncles in Tendermint - "logsBloom": bloom, - "stateRoot": hexutil.Bytes(header.AppHash), - "miner": validatorAddr, - "mixHash": common.Hash{}, - "difficulty": (*hexutil.Big)(big.NewInt(0)), - "extraData": "0x", - "size": hexutil.Uint64(size), - "gasLimit": hexutil.Uint64(gasLimit), // Static gas limit - "gasUsed": (*hexutil.Big)(gasUsed), + // #nosec G115 block height always positive + "number": hexutil.Uint64(header.Height), + "hash": hexutil.Bytes(header.Hash()), + "parentHash": common.BytesToHash(header.LastBlockID.Hash.Bytes()), + "nonce": ethtypes.BlockNonce{}, // PoW specific + "sha3Uncles": ethtypes.EmptyUncleHash, // No uncles in Tendermint + "logsBloom": bloom, + "stateRoot": hexutil.Bytes(header.AppHash), + "miner": validatorAddr, + "mixHash": common.Hash{}, + "difficulty": (*hexutil.Big)(big.NewInt(0)), + "extraData": "0x", + // #nosec G115 size always positive + "size": hexutil.Uint64(size), + // #nosec G115 gasLimit always positive + "gasLimit": hexutil.Uint64(gasLimit), // Static gas limit + "gasUsed": (*hexutil.Big)(gasUsed), + // #nosec G115 timestamp always positive "timestamp": hexutil.Uint64(header.Time.Unix()), "transactionsRoot": transactionsRoot, "receiptsRoot": ethtypes.EmptyRootHash, diff --git a/scripts/gosec.sh b/scripts/gosec.sh index 2b831a35e9..cfc2d603df 100644 --- a/scripts/gosec.sh +++ b/scripts/gosec.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -docker run -it --rm -w /node -v "$(pwd):/node" ghcr.io/zeta-chain/gosec:2.21.0-zeta -exclude-generated -exclude-dir testutil ./... \ No newline at end of file +docker run -it --rm -w /node -v "$(pwd):/node" ghcr.io/zeta-chain/gosec:2.21.4-zeta2 -exclude-generated -exclude-dir testutil ./... diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index b08fbea18c..3cd1ab3945 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -250,6 +250,7 @@ func (ob *Observer) CheckReceiptForBtcTxHash(ctx context.Context, txHash string, } // check confirmation + // #nosec G115 block height always positive if !ob.IsBlockConfirmed(uint64(blockVb.Height)) { return "", fmt.Errorf("block %d is not confirmed yet", blockVb.Height) } diff --git a/zetaclient/chains/evm/observer/inbound.go b/zetaclient/chains/evm/observer/inbound.go index 02ab1a0b6f..cb409f408e 100644 --- a/zetaclient/chains/evm/observer/inbound.go +++ b/zetaclient/chains/evm/observer/inbound.go @@ -38,7 +38,7 @@ import ( // TODO(revamp): move ticker function to a separate file func (ob *Observer) WatchInbound(ctx context.Context) error { sampledLogger := ob.Logger().Inbound.Sample(&zerolog.BasicSampler{N: 10}) - interval := ticker.SecondsFromUint64(ob.ChainParams().InboundTicker) + interval := ticker.DurationFromUint64Seconds(ob.ChainParams().InboundTicker) task := func(ctx context.Context, t *ticker.Ticker) error { return ob.watchInboundOnce(ctx, t, sampledLogger) } @@ -70,7 +70,7 @@ func (ob *Observer) watchInboundOnce(ctx context.Context, t *ticker.Ticker, samp ob.Logger().Inbound.Err(err).Msg("WatchInbound: observeInbound error") } - newInterval := ticker.SecondsFromUint64(ob.ChainParams().InboundTicker) + newInterval := ticker.DurationFromUint64Seconds(ob.ChainParams().InboundTicker) t.SetInterval(newInterval) return nil diff --git a/zetaclient/chains/evm/observer/outbound.go b/zetaclient/chains/evm/observer/outbound.go index 0bab913592..f8ce8f32ba 100644 --- a/zetaclient/chains/evm/observer/outbound.go +++ b/zetaclient/chains/evm/observer/outbound.go @@ -450,6 +450,7 @@ func (ob *Observer) FilterTSSOutboundInBlock(ctx context.Context, blockNumber ui for i := range block.Transactions { tx := block.Transactions[i] if ethcommon.HexToAddress(tx.From) == ob.TSS().EVMAddress() { + // #nosec G115 nonce always positive nonce := uint64(tx.Nonce) if !ob.IsTxConfirmed(nonce) { if receipt, txx, ok := ob.checkConfirmedTx(ctx, tx.Hash, nonce); ok { diff --git a/zetaclient/chains/ton/observer/inbound.go b/zetaclient/chains/ton/observer/inbound.go index 95f9a510d7..9a5e6ba548 100644 --- a/zetaclient/chains/ton/observer/inbound.go +++ b/zetaclient/chains/ton/observer/inbound.go @@ -31,7 +31,7 @@ func (ob *Observer) watchInbound(ctx context.Context) error { var ( chainID = ob.Chain().ChainId - initialInterval = ticker.SecondsFromUint64(ob.ChainParams().InboundTicker) + initialInterval = ticker.DurationFromUint64Seconds(ob.ChainParams().InboundTicker) sampledLogger = ob.Logger().Inbound.Sample(&zerolog.BasicSampler{N: 10}) ) @@ -47,7 +47,7 @@ func (ob *Observer) watchInbound(ctx context.Context) error { ob.Logger().Inbound.Err(err).Msg("WatchInbound: observeInbound error") } - newInterval := ticker.SecondsFromUint64(ob.ChainParams().InboundTicker) + newInterval := ticker.DurationFromUint64Seconds(ob.ChainParams().InboundTicker) t.SetInterval(newInterval) return nil diff --git a/zetaclient/orchestrator/orchestrator.go b/zetaclient/orchestrator/orchestrator.go index 698a520fcf..b63b7e3a00 100644 --- a/zetaclient/orchestrator/orchestrator.go +++ b/zetaclient/orchestrator/orchestrator.go @@ -618,7 +618,7 @@ func (oc *Orchestrator) ScheduleCctxSolana( oc.logger.Error().Msgf("ScheduleCctxSolana: chain observer is not a solana observer") return } - // #nosec G701 positive + // #nosec G115 positive interval := uint64(observer.ChainParams().OutboundScheduleInterval) // schedule keysign for each pending cctx diff --git a/zetaclient/types/dynamic_ticker.go b/zetaclient/types/dynamic_ticker.go index 103bfffb94..bfbc1e3cd4 100644 --- a/zetaclient/types/dynamic_ticker.go +++ b/zetaclient/types/dynamic_ticker.go @@ -23,7 +23,8 @@ func NewDynamicTicker(name string, interval uint64) (*DynamicTicker, error) { return &DynamicTicker{ name: name, interval: interval, - impl: time.NewTicker(time.Duration(interval) * time.Second), + // #nosec G115 interval is in range and not user controlled + impl: time.NewTicker(time.Duration(interval) * time.Second), }, nil } @@ -38,6 +39,7 @@ func (t *DynamicTicker) UpdateInterval(newInterval uint64, logger zerolog.Logger t.impl.Stop() oldInterval := t.interval t.interval = newInterval + // #nosec G115 interval is in range and not user controlled t.impl = time.NewTicker(time.Duration(t.interval) * time.Second) logger.Info().Msgf("%s ticker interval changed from %d to %d", t.name, oldInterval, newInterval) } diff --git a/zetaclient/zetacore/client_worker.go b/zetaclient/zetacore/client_worker.go index c5dcaa248d..b1fb4a6074 100644 --- a/zetaclient/zetacore/client_worker.go +++ b/zetaclient/zetacore/client_worker.go @@ -21,6 +21,7 @@ func (c *Client) UpdateAppContextWorker(ctx context.Context, app *appcontext.App }() var ( + // #nosec G115 interval is in range and not user controlled updateEvery = time.Duration(app.Config().ConfigUpdateTicker) * time.Second ticker = time.NewTicker(updateEvery) logger = c.logger.Sample(logSampler)