Advisories for Golang/Github.com/Klever-Io/Klever-Go package

2026

Klever-Go: Zombie-order theft: `Buy` missing `IsClaimed` guard in native marketplace

Location: core/kapp/market/market.go — Buy() (approx. L281–436) Severity: High The native marketplace enforces an IsClaimed guard in Claim (market.go:752), CancelOrder (market.go:1125), and orderEscrowAmount (market.go:251), but not in Buy. Marketplace escrow is virtual: the market KApp account never custodies currency. A bid burns funds from the bidder (bidderAcc.SubFromBalance, ~L378), and refunds/payouts mint to the recipient (AddToBalance, e.g. the prior-bidder refund at ~L349). Soundness depends on each order's CurrentBid being paid out exactly …

Klever-Go: Unauthenticated WebSocket /subscribe: no read-size limit, no connection cap, permissive origin -> remote node memory/goroutine exhaustion (DoS)

The unauthenticated WebSocket endpoint GET /subscribe is registered open: true by default (config/node/api.yaml) and lets a remote, unauthenticated client exhaust the node's memory and goroutines. Because the REST API runs IN-PROCESS with the node — network/api/api.go Start(…) ends with ws.Run(kleverFacade.RestAPIInterface()) — exhausting/killing the API process takes down the entire node, including its P2P and consensus participation. No API key, account, stake, or funds are required. Three compounding, independently-exploitable gaps stack …

Klever-Go: /log controls global node logging

An unauthenticated client can connect to GET /log, send an arbitrary logger profile as the first WebSocket message, and mutate the node's global logging configuration before receiving live logs from the process. I confirmed this against a local validator built from this repository: an unauthenticated client set the global log level to *:NONE, the node accepted the profile, and the node stopped emitting normal slot logs while the WebSocket connection …

Klever-Go Account takeover: `kleverUpdateAccountPermission` authorizes on attacker-controlled `RecipientAddr` instead of the authenticated caller

The VM built-in function KleverUpdateAccountPermission (registered always-active, creator.go:381-390 / core/vmconstants.go:234) rewrites an account's entire permission set. Its authorization check uses vmInput.RecipientAddr attacker-controlled instead of the authenticated vmInput.CallerAddr. The sibling handler kleverChangeOwnerAddress.go:86 uses vmInput.CallerAddr correctly, so the safe pattern exists in-repo; this handler deviates. The native transaction path (txProcess.go:833) is safe it uses tx.GetSender(). Mechanism: Wrong variable: CallerAddr is never referenced in the handler; auth is contractHasValidPermission(target.GetPermissions(), RecipientAddr), which returns true …

Klever: Marketplace settlement mints KLV when referral % + royalty % exceed the bid (negative seller share silently skipped)

When a marketplace order is settled (MarketBuy / BuyItNow, and auction Claim), the buyer's payment is split three ways — referral, royalties, and the seller (market-order owner) remainder: marketOwnerAmount = CurrentBid − referralAmount − royaltiesAmount Referral and royalties are paid out unconditionally, but the seller remainder is only paid when positive (computeMarketOwnerAmount returns Ok and pays nothing when the amount is <= 0). When referral% + royalty% exceeds 100% of …

Klever: Integer overflow in split-royalty validation enables unbounded minting of KLV (native token)

The per-entry percentages of a KDA asset's split royalties are validated by summing them into a uint32 accumulator and checking the sum against HundredPercent (10000), with no upper bound on each individual entry. Two split entries whose percentages sum to just over 2^32 wrap around below 10000 and pass validation, while each stored value remains astronomically large (e.g. 0x80000000 = 2,147,483,648 ≈ 21,474,836%). At royalty payout, each split recipient is …

klever-go: SFT add-quantity `int64` overflow bypasses a finite per-nonce MaxSupply

On the SFT add-quantity path the only supply bound is SFTAddCirculation, which does meta.Circulation += amount with no overflow guard, then checks if meta.Circulation > meta.MaxSupply && meta.MaxSupply != 0. If amount overflows int64 and wraps negative, negative > MaxSupply is false, the cap check passes, the function returns nil, and the balance credit stands. A nonce created with a finite MaxSupply (e.g. 1000) can thus be minted to ~MaxInt64 …

klever-go: Percentage-transfer royalty skips the source debit at exactly-100% splits

In processPercentageRoyaltiesTransfer the royalty pool is collected from the sender by SubFromBalance that is ordered after the split loop and after if royaltiesToPay <= 0 { return Ok }. The split-payout guard rejects only an allocation that exceeds the pool (a strict splitToPay > royaltiesToPay), so a split entry of exactly 100% (PercentTransferPercentage = 10000) is a valid config: it drives royaltiesToPay to 0 and hits the early-return before the …

klever-go: Unbounded goroutine spawn on direct-message ingress enables peer-driven DoS

networkMessenger.directMessageHandler in network/p2p/libp2p/netMessenger.go spawns a fresh goroutine for every incoming direct message before the antiflood layer makes an admission decision. There is no semaphore, throttler, or bound on concurrent in-flight spawns. A single connected libp2p peer can open a DirectSendID stream and send well-formed TopicMessage envelopes with varying sequence numbers. Each accepted direct message reaches directMessageHandler and triggers a fresh goroutine before processor.ProcessReceivedMessage runs. This allows unbounded goroutine growth and …

klever-go: REST API slow-header connection exhaustion via Gin Engine.Run

The Klever seednode REST API starts a Gin engine with Engine.Run(restAPIInterface). In Gin v1.9.1, Engine.Run calls Go's default http.ListenAndServe, which constructs an HTTP server without application-level ReadHeaderTimeout, ReadTimeout, or MaxHeaderBytes limits. An unauthenticated client that can reach a REST listener bound with Klever's documented –rest-api-interface :8080 all-interface option can hold incomplete HTTP headers open indefinitely. In a local proof against the real cmd/seednode/api.Start path on v1.7.17, 120 slow-header connections caused …

Klever-Go KVM: Unauthenticated remote node crash (nil-pointer DoS) in klever-go P2P transaction interceptor (txVersionChecker nil RawData) - potential chain halt

Every transaction gossiped on the klever-go P2P network is decoded and validated synchronously inside the libp2p pubsub topic-validator callback. The validator txVersionChecker.CheckTxVersion dereferences tx.RawData.Version with no nil check. A protobuf Transaction whose embedded RawData sub-message is omitted decodes to RawData == nil, so validating it triggers a nil-pointer panic. The libp2p pubsub callback, the underlying go-libp2p-pubsub validation worker, and klever's own network/p2p layer install no recover(), so the panic propagates …

Klever-Go KVM: Throttler slot leak in trie account-data sync causes epoch bootstrap / state sync DoS

The account-data trie syncers leak bounded throttler slots on error paths in syncDataTrie(). Each failed trie sync permanently consumes one slot from the NumGoRoutinesThrottler, and the slot is never returned unless the sync succeeds or the root hash was already present. I confirmed this on the current default branch develop at commit 9640d63 (observed on May 20, 2026). I also confirmed the bug with a runtime PoC using the real …

Klever-Go P2P MultiDataInterceptor leaks global throttler slots on malformed compressed batches (DoS)

The P2P MultiDataInterceptor starts throttled processing before it validates and decompresses a received batch. PreProcessMessage checks whether the global interceptor throttler can process the message and then calls StartProcessing(). After that point, ProcessReceivedMessage unmarshals the batch and enters the compressed-batch branch when b.IsCompressed is true. If b.Decompress() fails, the function logs the gzip error and returns immediately without calling EndProcessing(). This creates a permanent slot leak in the interceptor throttler. …

Klever-Go KVM read-only execution can commit contract delete and upgrade side effects

KVM exposes ExecuteReadOnlyWithTypedArguments as a read-only execution mechanism. The hook saves the previous read-only state, sets runtime.SetReadOnly(true), executes the destination context, and then restores the previous read-only state. However, the indirect contract delete and upgrade paths do not reject execution when runtime.ReadOnly() is true. As a result, a contract reached through read-only execution can call the production delete hook for a target contract it owns. The delete path appends the …

Klever-Go MultiDataInterceptor has remote OOM via crafted compressed P2P payload

A remote, unauthenticated denial-of-service vulnerability in Batch.Decompress (data/batch/batch.go) allows any peer that participates in a topic served by MultiDataInterceptor to allocate multi-gigabyte heaps on the receiving node from a sub-50 KiB gossip payload. A single packet is sufficient to OOM-kill a validator with conventional memory provisioning. Fleet-wide application affects chain liveness. The vulnerability was identified during an internal security review of core/process/interceptors/multiDataInterceptor.go at commit 405d01b0abbf0d3e73b4a990bd7394a01f200dc2. It is distinct from, and …