CWE-367
AllowedTime-of-check Time-of-use (TOCTOU) Race Condition
Abstraction: Base · Status: Incomplete
The product checks the state of a resource before using that resource, but the resource's state can change between the check and the use in a way that invalidates the results of the check.
1205 vulnerabilities reference this CWE, most recent first.
GHSA-MX2W-3QF4-9FFQ
Vulnerability from github – Published: 2026-08-03 03:31 – Updated: 2026-08-03 21:31In display, there is a possible escalation of privilege due to a race condition. This could lead to local escalation of privilege if a malicious actor has already obtained the System privilege. User interaction is not needed for exploitation. Patch ID: ALPS11019183; Issue ID: MSV-7758.
{
"affected": [],
"aliases": [
"CVE-2026-20474"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-03T03:16:42Z",
"severity": "MODERATE"
},
"details": "In display, there is a possible escalation of privilege due to a race condition. This could lead to local escalation of privilege if a malicious actor has already obtained the System privilege. User interaction is not needed for exploitation. Patch ID: ALPS11019183; Issue ID: MSV-7758.",
"id": "GHSA-mx2w-3qf4-9ffq",
"modified": "2026-08-03T21:31:32Z",
"published": "2026-08-03T03:31:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-20474"
},
{
"type": "WEB",
"url": "https://www.mediatek.com/product-security-bulletin/August-2026"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-MX4F-PJM3-X629
Vulnerability from github – Published: 2026-08-25 21:31 – Updated: 2026-08-26 21:31Race condition in WebProtect in Google Chrome prior to 152.0.7977.65 allowed a remote attacker who had compromised the renderer process to obtain sensitive information via a crafted HTML page. (Chromium security severity: Medium)
{
"affected": [],
"aliases": [
"CVE-2026-78991"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-25T21:17:55Z",
"severity": "MODERATE"
},
"details": "Race condition in WebProtect in Google Chrome prior to 152.0.7977.65 allowed a remote attacker who had compromised the renderer process to obtain sensitive information via a crafted HTML page. (Chromium security severity: Medium)",
"id": "GHSA-mx4f-pjm3-x629",
"modified": "2026-08-26T21:31:33Z",
"published": "2026-08-25T21:31:36Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-78991"
},
{
"type": "WEB",
"url": "https://chromereleases.googleblog.com/2026/08/stable-channel-update-for-desktop_0256176589.html"
},
{
"type": "WEB",
"url": "https://issues.chromium.org/issues/502888857"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-MXC8-4JQF-368Q
Vulnerability from github – Published: 2026-01-23 18:31 – Updated: 2026-01-23 20:16A TOCTOU and symlink race in svenstaro/miniserve 0.32.0 upload finalization (when uploads are enabled) can allow an attacker to overwrite arbitrary files outside the intended upload/document root in deployments where the attacker can create/replace filesystem entries in the upload destination directory (e.g., shared writable directory/volume).
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "miniserve"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.32.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-67124"
],
"database_specific": {
"cwe_ids": [
"CWE-367",
"CWE-59"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-23T20:16:21Z",
"nvd_published_at": "2026-01-23T16:15:52Z",
"severity": "MODERATE"
},
"details": "A TOCTOU and symlink race in svenstaro/miniserve 0.32.0 upload finalization (when uploads are enabled) can allow an attacker to overwrite arbitrary files outside the intended upload/document root in deployments where the attacker can create/replace filesystem entries in the upload destination directory (e.g., shared writable directory/volume).",
"id": "GHSA-mxc8-4jqf-368q",
"modified": "2026-01-23T20:16:21Z",
"published": "2026-01-23T18:31:28Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-67124"
},
{
"type": "WEB",
"url": "https://gist.github.com/thesmartshadow/55688f87f8b985eb530e07d00ef8c63f"
},
{
"type": "PACKAGE",
"url": "https://github.com/svenstaro/miniserve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "miniserve affected by a TOCTOU and symlink race vulnerability"
}
GHSA-P22W-HM7X-WWFC
Vulnerability from github – Published: 2023-02-27 21:30 – Updated: 2023-03-08 18:30A race condition was addressed with additional validation. This issue is fixed in macOS Ventura 13.2, iOS 16.3 and iPadOS 16.3. A user may be able to read arbitrary files as root.
{
"affected": [],
"aliases": [
"CVE-2023-23520"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-02-27T20:15:00Z",
"severity": "MODERATE"
},
"details": "A race condition was addressed with additional validation. This issue is fixed in macOS Ventura 13.2, iOS 16.3 and iPadOS 16.3. A user may be able to read arbitrary files as root.",
"id": "GHSA-p22w-hm7x-wwfc",
"modified": "2023-03-08T18:30:26Z",
"published": "2023-02-27T21:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-23520"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT213599"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT213601"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT213605"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT213606"
},
{
"type": "WEB",
"url": "https://support.apple.com/kb/HT213599"
},
{
"type": "WEB",
"url": "https://support.apple.com/kb/HT213601"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-P293-86CR-RJ34
Vulnerability from github – Published: 2025-03-07 18:31 – Updated: 2025-03-07 18:31A time-of-check time-of-use (TOCTOU) race condition vulnerability has been reported to affect several product versions. If exploited, the vulnerability could allow local attackers who have gained user access to gain access to otherwise unauthorized resources.
We have already fixed the vulnerability in the following versions: QVPN Device Client for Mac 2.2.5 and later Qsync for Mac 5.1.3 and later Qfinder Pro Mac 7.11.1 and later
{
"affected": [],
"aliases": [
"CVE-2024-53694"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-03-07T17:15:20Z",
"severity": "HIGH"
},
"details": "A time-of-check time-of-use (TOCTOU) race condition vulnerability has been reported to affect several product versions. If exploited, the vulnerability could allow local attackers who have gained user access to gain access to otherwise unauthorized resources.\n\nWe have already fixed the vulnerability in the following versions:\nQVPN Device Client for Mac 2.2.5 and later\nQsync for Mac 5.1.3 and later\nQfinder Pro Mac 7.11.1 and later",
"id": "GHSA-p293-86cr-rj34",
"modified": "2025-03-07T18:31:06Z",
"published": "2025-03-07T18:31:05Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-53694"
},
{
"type": "WEB",
"url": "https://www.qnap.com/en/security-advisory/qsa-24-51"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:A/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-P2M9-83F8-9277
Vulnerability from github – Published: 2022-05-24 17:23 – Updated: 2022-05-24 17:23Vulnerability in the Oracle VM VirtualBox product of Oracle Virtualization (component: Core). Supported versions that are affected are Prior to 5.2.44, prior to 6.0.24 and prior to 6.1.12. Difficult to exploit vulnerability allows high privileged attacker with logon to the infrastructure where Oracle VM VirtualBox executes to compromise Oracle VM VirtualBox. While the vulnerability is in Oracle VM VirtualBox, attacks may significantly impact additional products. Successful attacks of this vulnerability can result in takeover of Oracle VM VirtualBox. CVSS 3.1 Base Score 7.5 (Confidentiality, Integrity and Availability impacts). CVSS Vector: (CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H).
{
"affected": [],
"aliases": [
"CVE-2020-14677"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-07-15T18:15:00Z",
"severity": "MODERATE"
},
"details": "Vulnerability in the Oracle VM VirtualBox product of Oracle Virtualization (component: Core). Supported versions that are affected are Prior to 5.2.44, prior to 6.0.24 and prior to 6.1.12. Difficult to exploit vulnerability allows high privileged attacker with logon to the infrastructure where Oracle VM VirtualBox executes to compromise Oracle VM VirtualBox. While the vulnerability is in Oracle VM VirtualBox, attacks may significantly impact additional products. Successful attacks of this vulnerability can result in takeover of Oracle VM VirtualBox. CVSS 3.1 Base Score 7.5 (Confidentiality, Integrity and Availability impacts). CVSS Vector: (CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H).",
"id": "GHSA-p2m9-83f8-9277",
"modified": "2022-05-24T17:23:31Z",
"published": "2022-05-24T17:23:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-14677"
},
{
"type": "WEB",
"url": "https://security.gentoo.org/glsa/202101-09"
},
{
"type": "WEB",
"url": "https://www.oracle.com/security-alerts/cpujul2020.html"
},
{
"type": "WEB",
"url": "https://www.zerodayinitiative.com/advisories/ZDI-20-893"
},
{
"type": "WEB",
"url": "http://lists.opensuse.org/opensuse-security-announce/2020-09/msg00068.html"
},
{
"type": "WEB",
"url": "http://lists.opensuse.org/opensuse-security-announce/2020-09/msg00079.html"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-P3H5-95VP-QQR9
Vulnerability from github – Published: 2026-08-25 21:31 – Updated: 2026-08-28 00:31Race condition in Workers in Google Chrome prior to 152.0.7977.65 allowed a remote attacker who had compromised the renderer process to bypass web origin policy via a crafted HTML page. (Chromium security severity: Medium)
{
"affected": [],
"aliases": [
"CVE-2026-79267"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-25T21:18:21Z",
"severity": "MODERATE"
},
"details": "Race condition in Workers in Google Chrome prior to 152.0.7977.65 allowed a remote attacker who had compromised the renderer process to bypass web origin policy via a crafted HTML page. (Chromium security severity: Medium)",
"id": "GHSA-p3h5-95vp-qqr9",
"modified": "2026-08-28T00:31:58Z",
"published": "2026-08-25T21:31:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-79267"
},
{
"type": "WEB",
"url": "https://chromereleases.googleblog.com/2026/08/stable-channel-update-for-desktop_0256176589.html"
},
{
"type": "WEB",
"url": "https://issues.chromium.org/issues/497839983"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-P484-7M3W-W9XH
Vulnerability from github – Published: 2023-12-16 03:30 – Updated: 2023-12-20 18:30TOCTOU race-condition vulnerability in Insyde InsydeH2O with Kernel 5.2 before version 05.27.29, Kernel 5.3 before version 05.36.29, Kernel 5.4 version before 05.44.13, and Kernel 5.5 before version 05.52.13 allows an attacker to alter data and code used by the remainder of the boot process.
{
"affected": [],
"aliases": [
"CVE-2022-24351"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-12-16T02:15:07Z",
"severity": "MODERATE"
},
"details": "TOCTOU race-condition vulnerability in Insyde InsydeH2O with Kernel 5.2 before version 05.27.29, Kernel 5.3 before version 05.36.29, Kernel 5.4 version before 05.44.13, and Kernel 5.5 before version 05.52.13 allows an attacker to alter data and code used by the remainder of the boot process.",
"id": "GHSA-p484-7m3w-w9xh",
"modified": "2023-12-20T18:30:32Z",
"published": "2023-12-16T03:30:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-24351"
},
{
"type": "WEB",
"url": "https://www.insyde.com/security-pledge"
},
{
"type": "WEB",
"url": "https://www.insyde.com/security-pledge/SA-2023038"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-P64J-WWMG-JCP6
Vulnerability from github – Published: 2022-11-15 12:00 – Updated: 2022-11-18 18:30DMA transactions which are targeted at input buffers used for the AhciBusDxe software SMI handler could cause SMRAM corruption (a TOCTOU attack). DMA transactions which are targeted at input buffers used for the software SMI handler used by the AhciBusDxe driver could cause SMRAM corruption through a TOCTOU attack. This issue was discovered by Insyde engineering based on the general description provided by Intel's iSTARE group, Fixed in kernel 5.2: 05.27.23, kernel 5.3: 05.36.23, kernel 5.4: 05.44.23, kernel 5.5: 05.52.23 https://www.insyde.com/security-pledge/SA-2022047
{
"affected": [],
"aliases": [
"CVE-2022-33905"
],
"database_specific": {
"cwe_ids": [
"CWE-367"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-11-15T00:15:00Z",
"severity": "HIGH"
},
"details": "DMA transactions which are targeted at input buffers used for the AhciBusDxe software SMI handler could cause SMRAM corruption (a TOCTOU attack). DMA transactions which are targeted at input buffers used for the software SMI handler used by the AhciBusDxe driver could cause SMRAM corruption through a TOCTOU attack. This issue was discovered by Insyde engineering based on the general description provided by Intel\u0027s iSTARE group, Fixed in kernel 5.2: 05.27.23, kernel 5.3: 05.36.23, kernel 5.4: 05.44.23, kernel 5.5: 05.52.23 https://www.insyde.com/security-pledge/SA-2022047",
"id": "GHSA-p64j-wwmg-jcp6",
"modified": "2022-11-18T18:30:25Z",
"published": "2022-11-15T12:00:16Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-33905"
},
{
"type": "WEB",
"url": "https://www.insyde.com/security-pledge"
},
{
"type": "WEB",
"url": "https://www.insyde.com/security-pledge/SA-2022047"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-P7GW-2PCP-5PF8
Vulnerability from github – Published: 2026-08-28 16:22 – Updated: 2026-08-28 16:22Summary
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 the bid, marketOwnerAmount goes negative
and is silently skipped — so the marketplace pays out more KLV / sale currency than the buyer
paid in, minting the difference out of thin air.
The combined ceiling royalty% + referral% <= 100% is checked once, at listing time (Sell).
But the two percentages are sourced asymmetrically at settlement:
- referral % is snapshotted into the order at
Sell(MarketOrderData.ReferralPercentage); - royalty % is never snapshotted — it is read live from the asset at buy time
(
asset.Royalties.MarketPercentage).
So the listing-time invariant is a time-of-check/time-of-use guarantee only. After a valid
listing, the asset owner raises the royalty MarketPercentage via AssetTrigger → UpdateRoyalties;
at the next buy the live royalty plus the snapshotted referral exceed 100%, and the settlement mints
the overflow. The minted funds land in attacker-controlled referral / royalty addresses.
This was actively exploited on mainnet (see Evidence), minting tens of millions of KLV before the emergency guard was deployed.
Affected component
- Repository:
klever-io/klever-go(node). - Settlement / mint site:
core/kapp/market/market.go—executeBuyMarket(L575+),computeReferralAmount(L361+),computeRoyaltiesAmount(L490+),computeRoyaltiesFixedDeposit(L443+),computeMarketOwnerAmount(L540+). - TOCTOU sources:
Sellcombined check (market.go:908), order snapshot of referral but not royalty (market.go:997), live royalty mutation viacore/kapp/kda/trigger.go—handleUpdateRoyaltiesNFTandSFT(L613+, setsasset.Royalties.MarketPercentageat L670). - Reachable from both
Buy(BuyItNow,market.go:204+) and auctionClaim(market.go:705,market.go:731). - Pre-fix: not gated by any fork flag — exploitable on mainnet. The fix is gated behind the new
FixMarketBuyOverflowactivation-epoch flag.
Root cause
1. Settlement pays referral + royalty unconditionally, seller remainder only if positive
core/kapp/market/market.go — executeBuyMarket (L575+):
referralAmount, _ := tools.ComputePercentageI64(marketOrder.CurrentBid,
int64(marketOrder.ReferralPercentage), ...) // L583: SNAPSHOT referral %
royaltiesAmount, _ := tools.ComputePercentageI64(marketOrder.CurrentBid,
int64(asset.Royalties.MarketPercentage), ...) // L587: LIVE royalty %
marketOwnerAmount := marketOrder.CurrentBid - referralAmount - royaltiesAmount // L591: can go negative
// ---- FIX (FixMarketBuyOverflow), added by the patch ----
if m.forkController.FixMarketBuyOverflow() && marketOwnerAmount < 0 { // L593-596
ctx.Receipts().AddError(ctx.ContractID(), common.ErrFieldInvalidRoyalties, common.ErrInvalidValue.Error())
return transaction.Transaction_AmountInvalid, common.ErrInvalidValue
}
m.computeReferralAmount(ctx, marketOrder, referralAmount, currencyID) // pays referral in full
m.computeRoyaltiesFixedDeposit(ctx, marketOrder, asset) // pays fixed royalty (KLV)
m.computeRoyaltiesAmount(ctx, marketOrder, asset, currencyID, royaltiesAmount) // pays % royalty in full
m.computeMarketOwnerAmount(ctx, marketOrder, currencyID, marketOwnerAmount) // <-- skips when <= 0
computeMarketOwnerAmount (L540-542) — the silent skip:
func (m *marketKapp) computeMarketOwnerAmount(... marketOwnerAmount int64) (... , error) {
if marketOwnerAmount <= 0 {
return transaction.Transaction_Ok, nil // negative seller share dropped, NO error
}
// ... AddToBalance(marketOwnerAmount) ...
}
Meanwhile computeReferralAmount (L376) and computeRoyaltiesAmount (L515) each AddToBalance(...)
the full computed amount with no matching debit from the buyer beyond the single
bidderAcc.SubFromBalance(amount) taken in Buy (market.go:301).
Conservation breaks: buyer is debited bid once; recipients are credited
referralAmount + royaltiesAmount. When that sum > bid, the surplus
(referralAmount + royaltiesAmount − bid) is minted.
2. The combined ≤100% invariant is enforced only at listing time
Sell (market.go:908) correctly rejects a listing whose combined cut exceeds 100%:
if asset.Royalties.MarketPercentage + marketplace.ReferralPercentage > core.HundredPercent {
return transaction.Transaction_ParameterInvalid, common.ErrInvalidValue
}
…and snapshots referral into the order, but not royalty (market.go:997-998):
marketOrder := &kapps.MarketOrderData{
// ...
ReferralPercentage: marketplace.ReferralPercentage, // snapshotted
RoyaltiesFixedDeposit: asset.Royalties.MarketFixed, // snapshotted
// NOTE: asset.Royalties.MarketPercentage is NOT snapshotted -> read live at buy
}
MarketOrderData has no field for the royalty percentage (kapps/market.pb.go), so settlement
always re-reads it live from the (mutable) asset.
3. Royalty % is mutable after listing
core/kapp/kda/trigger.go — handleUpdateRoyaltiesNFTandSFT (L613+) lets the asset owner overwrite
asset.Royalties.MarketPercentage (L670) with only a per-field <= 100% check (CheckValid100Params,
L651) — it has no knowledge of any outstanding marketplace listing's snapshotted referral. So the
owner can list at, e.g., referral 100% / royalty 0% (sum 100%, passes Sell), then raise royalty to
100%, making the buy-time sum 200%.
The shipped emergency-guard source documents this exact vector: "The royalty percentage is read live at buy time, so a listing made now can be weaponised later via UpdateRoyalties." (
common/emergencyGuard.go)
Net effect: referralAmount + royaltiesAmount = bid + bid = 2·bid; marketOwnerAmount = −bid
(skipped); bid KLV minted per settlement, paid to attacker-controlled addresses.
Proof of Concept
A. Committed regression test (deterministic, runnable today)
core/kapp/market/market_test.go — TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation.
It builds an order with ReferralPercentage = 100% and an asset with MarketPercentage = 100%
(the attacker is both the referral and the royalty address), then settles a bid of
25,600,000 KLV (25600000000000 base units):
go test ./core/kapp/market/ -run TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation -v
FixDisabled_MintsKLVFromThinAir: settlement returnsOk; the attacker address ends with2·bidcredited while onlybidwas paid in — i.e.bidKLV minted.FixEnabled_RejectsInflation: withFixMarketBuyOverflowon, settlement returnsTransaction_AmountInvalidand the attacker balance stays0— no payout runs.
B. End-to-end on a local node (the real attack path)
A single-node local network is sufficient. The exploit is four transactions from one ordinary funded account; nothing privileged is required.
- Create an NFT collection you own, with
royalties.marketPercentage = 0and a royalties address you control. - Create a marketplace with
referralPercentage = 10000(100%) and a referral address you control (CreateMarketplace). - List one NFT for sale (
Sell) on that marketplace. TheSellcheck passes because0 (royalty) + 10000 (referral) = 10000 = HundredPercent. The order snapshotsReferralPercentage = 10000. - Raise the royalty on the asset to 100% (
AssetTrigger / UpdateRoyalties,marketPercentage = 10000). Allowed: the per-field check passes and the live combined invariant is never re-evaluated against the open listing. - Buy the listing (
MarketBuy) from a second account (or settle the auction viaClaim).referralAmount = bid,royaltiesAmount = bid,marketOwnerAmount = −bid(skipped). Your referral + royalty addresses receive2·bid; the buyer paidbid;bidKLV is minted.
Because the attacker controls buyer, seller, referral and royalty addresses, the only real cost is transaction fees; the cycle is repeatable until supply targets are met.
Evidence
Regression test (local, verbatim)
=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation
=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixDisabled_MintsKLVFromThinAir
=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixEnabled_RejectsInflation
--- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation (0.00s)
--- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixDisabled_MintsKLVFromThinAir (0.00s)
--- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixEnabled_RejectsInflation (0.00s)
PASS
ok github.com/klever-io/klever-go/core/kapp/market 0.279s
FixDisabled asserts the attacker balance equals 2·bid = 51,200,000 KLV for a single settlement
(bid = 25,600,000 KLV), with bid of that minted. FixEnabled asserts rejection and a 0
balance.
Mainnet exploitation (observed)
The bug was exploited in production, and was detected and characterised externally by the community monitoring project KleverPuls / kpulse.tech before the root cause was known internally. Over a ~24h window kpulse isolated a single wallet (opened 2026-06-04, ~204 transactions in ~24h, funded only by a ~242K KLV KuCoin withdrawal, no treasury/foundation funding) that:
- self-issued 3 NFT collections named "InflationPOC" and wash-traded one (
NFLATION-ESGO/1) 29 times through self-created marketplaces — ~$450K of artificial, economically empty NFT volume; - swapped the proceeds KLV → USDC / USDT / WBTC / WETH on KleverSwap and bridged ~$72K of value to Ethereum via wrapped-asset burns over 24h (USDC −12,487 ≈ $12.5K; USDT −26,362 ≈ $26.4K; WBTC −0.31 ≈ $19.6K; WETH −7.55 ≈ $14K);
- surfaced a spurious "1.86B KLV outflow" headline that kpulse correctly identified as a wash-trade receipt-doubling artifact with small real net KLV flow.
That "doubling of marketplace receipts" is precisely the on-chain signature of this bug: each
abusive settlement pays out a referral cut (bid) plus a royalty cut (bid) while the buyer paid
only bid once — the market contract emits ~2× the value it took in, which is the mint. The
attacker's self-issued collection and self-created marketplaces are exactly the self-dealing setup the
regression test reproduces (the test reuses the real on-chain identifiers: collectionID =
"NFLATION-ESGO", asset 1, market name "Inflation Market").
kpulse could not determine the cause from on-chain data alone and flagged the activity for confirmation; the Klever core team then traced it to the referral+royalty settlement defect described above and shipped the emergency guard + protocol fix.
Each abusive settlement minted one bid of KLV; the observed bid was 25,600,000 KLV, repeated and
funnelled through a short hop chain before being swapped and bridged. The emergency guard
(common/emergencyGuard.go) blocks the following observed sender public keys (hex):
| Public key (hex) | Address | Role (observed) |
|---|---|---|
54ea28e527d4136508be955374afa54a8c25c19a48c674f412f7ce02db0f4e1b |
klv12n4z3ef86sfk2z97j4fhfta9f2xztsv6frr8faqj7l8q9kc0fcdsfjfqez |
root / minter |
bb687dbba23e1844fec674a32cb8809f0d3207506c53fc3d637e40dc56708d63 |
klv1hd58mwaz8cvyflkxwj3jewyqnuxnyp6sd3flc0tr0eqdc4ns343skngdjq |
collector hop (~125M KLV) |
77388d3dfe6cd88e8da723254c11abf3d9cccb6fb77b000e5038fc3ff92b964d |
klv1wuug6007dnvgard8yvj5cydt70vuejm0kaasqrjs8r7rl7ftjexsglalf6 |
direct recipient (25.6M, idle) |
a196789b026f996867f08317cc6c5a4eb9ad3a59b1be3716420bc8692d4c3048 |
klv15xt83xczd7vkselssvtucmz6f6u66wjekxlrw9jzp0yxjt2vxpyq2nawrw |
hop-2 recipient (25M) |
The single-bid per-settlement size (25.6M KLV) matches the "direct recipient, 25.6M" entry, and the
~125M at the collector hop is consistent with roughly five abusive settlements.
Impact
- Unbounded inflation of KLV (and of any sale currency used for the listing), repeatable for only transaction fees, by any account that creates its own collection + marketplace.
- The minted KLV is created by direct
AddToBalanceto attacker addresses (no trackedMint), so the asset's booked supply does not change — the inflation is off the books and only detectable by summing balances / auditing receipts (it surfaces on-chain as doubled marketplace receipts). - Realized impact (observed): the attacker minted KLV via ~29 self-dealt settlements, swapped to stable/wrapped assets on KleverSwap, and off-ramped ~$72K to Ethereum via the bridge (USDC, USDT, WBTC, WETH) before the emergency guard halted the activity, alongside ~$450K of artificial NFT wash-trade volume.
- Total loss of economic integrity for all KLV / token holders.
Who can exploit it / prerequisites
- Any account that can pay the one-time collection-create + marketplace-create fees and tx fees. No roles, admin, or allowlist.
- Any client. The settlement is triggered by standard
MarketBuy/Claimcontracts POSTed to the public, unauthenticated/transaction/sendRPC (network/api/transaction/routes.go,SendTX/BroadcastTX). TheoperatorCLI, the SDKs, or a hand-signedcurlall work. - Deterministic; the abusive state is reached with one extra
UpdateRoyaltiesafter a normal listing.
Remediation
Shipped as a layered response (embargoed):
Layer 0 — emergency guard (deployed first, fork-proof) — GHSA-p7gw rc1
common/emergencyGuard.go + data/transaction/emergencyGuard.go: matching transactions are kept
out of blocks this node proposes (core/process/block/preprocess/transactions.go) and refused at
the node API (node.go SendTransaction / SendBulkTransactions). It never changes block
validity, so a partial-fleet rollout cannot fork the chain. It blocks the known attacker senders
(all contract types) plus all MarketBuy, Sell, and CreateMarketplace / ConfigMarketplace
operations while the protocol fix rolls out. Enforcement is by proposer cooperation, not protocol —
coverage equals the share of block producers running the guard.
Layer 1 — protocol fix (consensus, epoch-gated) — GHSA-p7gw rc2
core/kapp/market/market.go:593 rejects the settlement when marketOwnerAmount < 0, before any
payout runs, returning Transaction_AmountInvalid. Gated behind the new FixMarketBuyOverflow
activation-epoch flag (config/enableEpochs.*, core/fork/forks.go, core/interface.go) so
historical blocks reprocess identically. Covered by
TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation.
Recommended hardening (defense in depth)
- Snapshot the royalty % into
MarketOrderDataatSell(as referral already is) and pay from the snapshot, eliminating the TOCTOU entirely; or re-evaluate the combinedreferral% + royalty% <= 100%invariant at settlement. - Treat a negative seller remainder as a hard error everywhere, and only treat exactly
0as a no-op skip (computeMarketOwnerAmount), so a future regression aborts the tx instead of minting. - After splitting a payment pool, assert conservation (
referral + royalties + ownerShare == bid) so any drift aborts the transaction.
Notes
- Triggered by both BuyItNow (
Buy) and auction settlement (Claim). - The same family of "pay full cut, silently drop the negative remainder" minting also exists in the
royalty-split paths and is tracked separately under GHSA-cgc5-v3f2-8m2v (split-royalty
uint32overflow). This advisory covers the top-level referral+royalty > bid case; theFixMarketBuyOverflowguard here only checksmarketOwnerAmount, not intra-split over-payments.
Acknowledgments
- KleverPuls / kpulse.tech — community monitoring project that first
detected and characterised the exploitation in the wild. kpulse isolated the attacker wallet and
its "InflationPOC" collections, identified the marketplace wash-trading of
NFLATION-ESGO/1and the KleverSwap → bridge off-ramp (~$72K to Ethereum), and flagged the anomalous doubling of marketplace receipts — the exact on-chain signature of this bug — prompting the incident response that led to this fix. The root cause was then identified and remediated by the Klever core team.
Source
- Vulnerable / fixed code:
core/kapp/market/market.go:540-545,575-596,908,997-998,core/kapp/kda/trigger.go:613-676,core/process/kda/assetHelper.go:101,tools/converters.go:102,core/constants.go:18. - Emergency guard:
common/emergencyGuard.go,data/transaction/emergencyGuard.go,core/process/block/preprocess/transactions.go,node/node.go. - Fork flag:
config/enableEpochs.go,config/node/enableEpochs.yaml,core/fork/forks.go,core/interface.go. - Regression test:
core/kapp/market/market_test.go(TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation).
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/klever-io/klever-go"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.7.19"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54754"
],
"database_specific": {
"cwe_ids": [
"CWE-191",
"CWE-367",
"CWE-682"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-28T16:22:15Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "## Summary\n\nWhen a marketplace order is settled (`MarketBuy` / `BuyItNow`, and auction `Claim`), the buyer\u0027s\npayment is split three ways \u2014 **referral**, **royalties**, and the **seller (market-order owner)\nremainder**:\n\n```\nmarketOwnerAmount = CurrentBid \u2212 referralAmount \u2212 royaltiesAmount\n```\n\nReferral and royalties are paid out **unconditionally**, but the seller remainder is only paid\n**when positive** (`computeMarketOwnerAmount` returns `Ok` and pays nothing when the amount is\n`\u003c= 0`). When `referral% + royalty%` exceeds 100% of the bid, `marketOwnerAmount` goes **negative**\nand is silently skipped \u2014 so the marketplace pays out **more KLV / sale currency than the buyer\npaid in**, minting the difference out of thin air.\n\nThe combined ceiling `royalty% + referral% \u003c= 100%` **is** checked once, at listing time (`Sell`).\nBut the two percentages are sourced asymmetrically at settlement:\n\n- **referral %** is **snapshotted** into the order at `Sell` (`MarketOrderData.ReferralPercentage`);\n- **royalty %** is **never snapshotted** \u2014 it is read **live** from the asset at buy time\n (`asset.Royalties.MarketPercentage`).\n\nSo the listing-time invariant is a **time-of-check/time-of-use** guarantee only. After a valid\nlisting, the asset owner raises the royalty `MarketPercentage` via `AssetTrigger \u2192 UpdateRoyalties`;\nat the next buy the live royalty plus the snapshotted referral exceed 100%, and the settlement mints\nthe overflow. The minted funds land in attacker-controlled referral / royalty addresses.\n\nThis was **actively exploited on mainnet** (see *Evidence*), minting tens of millions of KLV before\nthe emergency guard was deployed.\n\n## Affected component\n\n- Repository: `klever-io/klever-go` (node).\n- Settlement / mint site: `core/kapp/market/market.go` \u2014 `executeBuyMarket` (L575+),\n `computeReferralAmount` (L361+), `computeRoyaltiesAmount` (L490+),\n `computeRoyaltiesFixedDeposit` (L443+), `computeMarketOwnerAmount` (L540+).\n- TOCTOU sources: `Sell` combined check (`market.go:908`), order snapshot of referral but **not**\n royalty (`market.go:997`), live royalty mutation via\n `core/kapp/kda/trigger.go` \u2014 `handleUpdateRoyaltiesNFTandSFT` (L613+, sets\n `asset.Royalties.MarketPercentage` at L670).\n- Reachable from both `Buy` (BuyItNow, `market.go:204+`) and auction `Claim`\n (`market.go:705`, `market.go:731`).\n- Pre-fix: **not** gated by any fork flag \u2014 exploitable on mainnet. The fix is gated behind the new\n `FixMarketBuyOverflow` activation-epoch flag.\n\n---\n\n## Root cause\n\n### 1. Settlement pays referral + royalty unconditionally, seller remainder only if positive\n`core/kapp/market/market.go` \u2014 `executeBuyMarket` (L575+):\n```go\nreferralAmount, _ := tools.ComputePercentageI64(marketOrder.CurrentBid,\n int64(marketOrder.ReferralPercentage), ...) // L583: SNAPSHOT referral %\nroyaltiesAmount, _ := tools.ComputePercentageI64(marketOrder.CurrentBid,\n int64(asset.Royalties.MarketPercentage), ...) // L587: LIVE royalty %\nmarketOwnerAmount := marketOrder.CurrentBid - referralAmount - royaltiesAmount // L591: can go negative\n\n// ---- FIX (FixMarketBuyOverflow), added by the patch ----\nif m.forkController.FixMarketBuyOverflow() \u0026\u0026 marketOwnerAmount \u003c 0 { // L593-596\n ctx.Receipts().AddError(ctx.ContractID(), common.ErrFieldInvalidRoyalties, common.ErrInvalidValue.Error())\n return transaction.Transaction_AmountInvalid, common.ErrInvalidValue\n}\n\nm.computeReferralAmount(ctx, marketOrder, referralAmount, currencyID) // pays referral in full\nm.computeRoyaltiesFixedDeposit(ctx, marketOrder, asset) // pays fixed royalty (KLV)\nm.computeRoyaltiesAmount(ctx, marketOrder, asset, currencyID, royaltiesAmount) // pays % royalty in full\nm.computeMarketOwnerAmount(ctx, marketOrder, currencyID, marketOwnerAmount) // \u003c-- skips when \u003c= 0\n```\n`computeMarketOwnerAmount` (L540-542) \u2014 the silent skip:\n```go\nfunc (m *marketKapp) computeMarketOwnerAmount(... marketOwnerAmount int64) (... , error) {\n\tif marketOwnerAmount \u003c= 0 {\n\t\treturn transaction.Transaction_Ok, nil // negative seller share dropped, NO error\n\t}\n\t// ... AddToBalance(marketOwnerAmount) ...\n}\n```\nMeanwhile `computeReferralAmount` (L376) and `computeRoyaltiesAmount` (L515) each `AddToBalance(...)`\nthe full computed amount with **no matching debit** from the buyer beyond the single\n`bidderAcc.SubFromBalance(amount)` taken in `Buy` (`market.go:301`).\n\n**Conservation breaks:** buyer is debited `bid` once; recipients are credited\n`referralAmount + royaltiesAmount`. When that sum `\u003e bid`, the surplus\n`(referralAmount + royaltiesAmount \u2212 bid)` is **minted**.\n\n### 2. The combined \u2264100% invariant is enforced only at listing time\n`Sell` (`market.go:908`) correctly rejects a listing whose combined cut exceeds 100%:\n```go\nif asset.Royalties.MarketPercentage + marketplace.ReferralPercentage \u003e core.HundredPercent {\n\treturn transaction.Transaction_ParameterInvalid, common.ErrInvalidValue\n}\n```\n\u2026and snapshots **referral** into the order, but **not** royalty (`market.go:997-998`):\n```go\nmarketOrder := \u0026kapps.MarketOrderData{\n\t// ...\n\tReferralPercentage: marketplace.ReferralPercentage, // snapshotted\n\tRoyaltiesFixedDeposit: asset.Royalties.MarketFixed, // snapshotted\n\t// NOTE: asset.Royalties.MarketPercentage is NOT snapshotted -\u003e read live at buy\n}\n```\n`MarketOrderData` has no field for the royalty percentage (`kapps/market.pb.go`), so settlement\nalways re-reads it live from the (mutable) asset.\n\n### 3. Royalty % is mutable after listing\n`core/kapp/kda/trigger.go` \u2014 `handleUpdateRoyaltiesNFTandSFT` (L613+) lets the asset owner overwrite\n`asset.Royalties.MarketPercentage` (L670) with only a **per-field** `\u003c= 100%` check (`CheckValid100Params`,\nL651) \u2014 it has no knowledge of any outstanding marketplace listing\u0027s snapshotted referral. So the\nowner can list at, e.g., referral 100% / royalty 0% (sum 100%, passes `Sell`), then raise royalty to\n100%, making the buy-time sum 200%.\n\n\u003e The shipped emergency-guard source documents this exact vector:\n\u003e *\"The royalty percentage is read live at buy time, so a listing made now can be weaponised later\n\u003e via UpdateRoyalties.\"* (`common/emergencyGuard.go`)\n\n**Net effect:** `referralAmount + royaltiesAmount = bid + bid = 2\u00b7bid`; `marketOwnerAmount = \u2212bid`\n(skipped); **`bid` KLV minted per settlement**, paid to attacker-controlled addresses.\n\n---\n\n## Proof of Concept\n\n### A. Committed regression test (deterministic, runnable today)\n`core/kapp/market/market_test.go` \u2014 `TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation`.\nIt builds an order with `ReferralPercentage = 100%` and an asset with `MarketPercentage = 100%`\n(the attacker is both the referral and the royalty address), then settles a `bid` of\n`25,600,000 KLV` (`25600000000000` base units):\n\n```bash\ngo test ./core/kapp/market/ -run TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation -v\n```\n\n- `FixDisabled_MintsKLVFromThinAir`: settlement returns `Ok`; the attacker address ends with\n `2\u00b7bid` credited while only `bid` was paid in \u2014 i.e. **`bid` KLV minted**.\n- `FixEnabled_RejectsInflation`: with `FixMarketBuyOverflow` on, settlement returns\n `Transaction_AmountInvalid` and the attacker balance stays `0` \u2014 **no payout runs**.\n\n### B. End-to-end on a local node (the real attack path)\nA single-node local network is sufficient. The exploit is four transactions from one ordinary\nfunded account; nothing privileged is required.\n\n1. **Create an NFT collection** you own, with `royalties.marketPercentage = 0` and a royalties\n address you control.\n2. **Create a marketplace** with `referralPercentage = 10000` (100%) and a referral address you\n control (`CreateMarketplace`).\n3. **List** one NFT for sale (`Sell`) on that marketplace. The `Sell` check passes because\n `0 (royalty) + 10000 (referral) = 10000 = HundredPercent`. The order snapshots\n `ReferralPercentage = 10000`.\n4. **Raise the royalty** on the asset to 100% (`AssetTrigger / UpdateRoyalties`,\n `marketPercentage = 10000`). Allowed: the per-field check passes and the live combined invariant\n is never re-evaluated against the open listing.\n5. **Buy** the listing (`MarketBuy`) from a second account (or settle the auction via `Claim`).\n `referralAmount = bid`, `royaltiesAmount = bid`, `marketOwnerAmount = \u2212bid` (skipped). Your\n referral + royalty addresses receive `2\u00b7bid`; the buyer paid `bid`; **`bid` KLV is minted**.\n\nBecause the attacker controls buyer, seller, referral and royalty addresses, the only real cost is\ntransaction fees; the cycle is repeatable until supply targets are met.\n\n---\n\n## Evidence\n\n### Regression test (local, verbatim)\n```\n=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation\n=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixDisabled_MintsKLVFromThinAir\n=== RUN TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixEnabled_RejectsInflation\n--- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation (0.00s)\n --- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixDisabled_MintsKLVFromThinAir (0.00s)\n --- PASS: TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation/FixEnabled_RejectsInflation (0.00s)\nPASS\nok \tgithub.com/klever-io/klever-go/core/kapp/market\t0.279s\n```\n`FixDisabled` asserts the attacker balance equals `2\u00b7bid = 51,200,000 KLV` for a single settlement\n(`bid = 25,600,000 KLV`), with `bid` of that minted. `FixEnabled` asserts rejection and a `0`\nbalance.\n\n### Mainnet exploitation (observed)\nThe bug was exploited in production, and was **detected and characterised externally** by the\ncommunity monitoring project **[KleverPuls / kpulse.tech](https://kpulse.tech)** before the root\ncause was known internally. Over a ~24h window kpulse isolated a single wallet (opened\n**2026-06-04**, ~**204 transactions** in ~24h, funded only by a ~**242K KLV KuCoin withdrawal**, no\ntreasury/foundation funding) that:\n\n- **self-issued 3 NFT collections named \"InflationPOC\"** and **wash-traded one (`NFLATION-ESGO/1`)\n 29 times** through self-created marketplaces \u2014 ~**$450K of artificial, economically empty NFT\n volume**;\n- **swapped the proceeds KLV \u2192 USDC / USDT / WBTC / WETH on KleverSwap** and **bridged ~$72K of value\n to Ethereum** via wrapped-asset burns over 24h (USDC \u221212,487 \u2248 $12.5K; USDT \u221226,362 \u2248 $26.4K; WBTC\n \u22120.31 \u2248 $19.6K; WETH \u22127.55 \u2248 $14K);\n- surfaced a spurious **\"1.86B KLV outflow\"** headline that kpulse correctly identified as a\n wash-trade **receipt-doubling** artifact with small real net KLV flow.\n\nThat \"doubling of marketplace receipts\" is **precisely the on-chain signature of this bug**: each\nabusive settlement pays out a referral cut (`bid`) **plus** a royalty cut (`bid`) while the buyer paid\nonly `bid` once \u2014 the market contract emits ~2\u00d7 the value it took in, which *is* the mint. The\nattacker\u0027s self-issued collection and self-created marketplaces are exactly the self-dealing setup the\nregression test reproduces (the test reuses the real on-chain identifiers: `collectionID =\n\"NFLATION-ESGO\"`, asset `1`, market name \"Inflation Market\").\n\nkpulse could not determine the cause from on-chain data alone and flagged the activity for\nconfirmation; the Klever core team then traced it to the referral+royalty settlement defect described\nabove and shipped the emergency guard + protocol fix.\n\nEach abusive settlement minted one `bid` of KLV; the observed `bid` was `25,600,000 KLV`, repeated and\nfunnelled through a short hop chain before being swapped and bridged. The emergency guard\n(`common/emergencyGuard.go`) blocks the following observed sender public keys (hex):\n\n| Public key (hex) | Address | Role (observed) |\n|---|---|---|\n| `54ea28e527d4136508be955374afa54a8c25c19a48c674f412f7ce02db0f4e1b` | `klv12n4z3ef86sfk2z97j4fhfta9f2xztsv6frr8faqj7l8q9kc0fcdsfjfqez` | root / minter |\n| `bb687dbba23e1844fec674a32cb8809f0d3207506c53fc3d637e40dc56708d63` | `klv1hd58mwaz8cvyflkxwj3jewyqnuxnyp6sd3flc0tr0eqdc4ns343skngdjq` | collector hop (~125M KLV) |\n| `77388d3dfe6cd88e8da723254c11abf3d9cccb6fb77b000e5038fc3ff92b964d` | `klv1wuug6007dnvgard8yvj5cydt70vuejm0kaasqrjs8r7rl7ftjexsglalf6` | direct recipient (25.6M, idle) |\n| `a196789b026f996867f08317cc6c5a4eb9ad3a59b1be3716420bc8692d4c3048` | `klv15xt83xczd7vkselssvtucmz6f6u66wjekxlrw9jzp0yxjt2vxpyq2nawrw` | hop-2 recipient (25M) |\n\nThe single-`bid` per-settlement size (25.6M KLV) matches the \"direct recipient, 25.6M\" entry, and the\n~125M at the collector hop is consistent with roughly five abusive settlements.\n\n---\n\n## Impact\n\n- **Unbounded inflation of KLV** (and of any sale currency used for the listing), repeatable for only\n transaction fees, by any account that creates its own collection + marketplace.\n- The minted KLV is created by direct `AddToBalance` to attacker addresses (no tracked `Mint`), so\n the asset\u0027s booked supply does not change \u2014 the inflation is **off the books** and only detectable\n by summing balances / auditing receipts (it surfaces on-chain as *doubled* marketplace receipts).\n- **Realized impact (observed):** the attacker minted KLV via ~29 self-dealt settlements, swapped to\n stable/wrapped assets on KleverSwap, and **off-ramped ~$72K to Ethereum via the bridge** (USDC,\n USDT, WBTC, WETH) before the emergency guard halted the activity, alongside ~$450K of artificial\n NFT wash-trade volume.\n- Total loss of economic integrity for all KLV / token holders.\n\n## Who can exploit it / prerequisites\n\n- **Any account** that can pay the one-time collection-create + marketplace-create fees and tx\n fees. No roles, admin, or allowlist.\n- **Any client.** The settlement is triggered by standard `MarketBuy` / `Claim` contracts POSTed to\n the public, unauthenticated `/transaction/send` RPC (`network/api/transaction/routes.go`,\n `SendTX` / `BroadcastTX`). The `operator` CLI, the SDKs, or a hand-signed `curl` all work.\n- Deterministic; the abusive state is reached with one extra `UpdateRoyalties` after a normal listing.\n\n---\n\n## Remediation\n\nShipped as a layered response (embargoed):\n\n### Layer 0 \u2014 emergency guard (deployed first, fork-proof) \u2014 `GHSA-p7gw` rc1\n`common/emergencyGuard.go` + `data/transaction/emergencyGuard.go`: matching transactions are kept\nout of blocks this node proposes (`core/process/block/preprocess/transactions.go`) and refused at\nthe node API (`node.go` `SendTransaction` / `SendBulkTransactions`). It **never changes block\nvalidity**, so a partial-fleet rollout cannot fork the chain. It blocks the known attacker senders\n(all contract types) plus all `MarketBuy`, `Sell`, and `CreateMarketplace` / `ConfigMarketplace`\noperations while the protocol fix rolls out. Enforcement is by proposer cooperation, not protocol \u2014\ncoverage equals the share of block producers running the guard.\n\n### Layer 1 \u2014 protocol fix (consensus, epoch-gated) \u2014 `GHSA-p7gw` rc2\n`core/kapp/market/market.go:593` rejects the settlement when `marketOwnerAmount \u003c 0`, **before any\npayout runs**, returning `Transaction_AmountInvalid`. Gated behind the new `FixMarketBuyOverflow`\nactivation-epoch flag (`config/enableEpochs.*`, `core/fork/forks.go`, `core/interface.go`) so\nhistorical blocks reprocess identically. Covered by\n`TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation`.\n\n### Recommended hardening (defense in depth)\n1. **Snapshot the royalty %** into `MarketOrderData` at `Sell` (as referral already is) and pay from\n the snapshot, eliminating the TOCTOU entirely; or re-evaluate the combined\n `referral% + royalty% \u003c= 100%` invariant at settlement.\n2. Treat a **negative** seller remainder as a hard error everywhere, and only treat exactly `0` as a\n no-op skip (`computeMarketOwnerAmount`), so a future regression aborts the tx instead of minting.\n3. After splitting a payment pool, **assert conservation** (`referral + royalties + ownerShare == bid`)\n so any drift aborts the transaction.\n\n---\n\n## Notes\n\n- Triggered by both BuyItNow (`Buy`) and auction settlement (`Claim`).\n- The same family of \"pay full cut, silently drop the negative remainder\" minting also exists in the\n royalty-split paths and is tracked separately under **GHSA-cgc5-v3f2-8m2v** (split-royalty `uint32`\n overflow). This advisory covers the top-level referral+royalty \u003e bid case; the\n `FixMarketBuyOverflow` guard here only checks `marketOwnerAmount`, not intra-split over-payments.\n\n## Acknowledgments\n\n- **[KleverPuls / kpulse.tech](https://kpulse.tech)** \u2014 community monitoring project that **first\n detected and characterised the exploitation in the wild**. kpulse isolated the attacker wallet and\n its \"InflationPOC\" collections, identified the marketplace wash-trading of `NFLATION-ESGO/1` and the\n KleverSwap \u2192 bridge off-ramp (~$72K to Ethereum), and flagged the anomalous *doubling* of\n marketplace receipts \u2014 the exact on-chain signature of this bug \u2014 prompting the incident response\n that led to this fix. The root cause was then identified and remediated by the Klever core team.\n\n## Source\n\n- Vulnerable / fixed code: `core/kapp/market/market.go:540-545,575-596,908,997-998`,\n `core/kapp/kda/trigger.go:613-676`, `core/process/kda/assetHelper.go:101`,\n `tools/converters.go:102`, `core/constants.go:18`.\n- Emergency guard: `common/emergencyGuard.go`, `data/transaction/emergencyGuard.go`,\n `core/process/block/preprocess/transactions.go`, `node/node.go`.\n- Fork flag: `config/enableEpochs.go`, `config/node/enableEpochs.yaml`, `core/fork/forks.go`,\n `core/interface.go`.\n- Regression test: `core/kapp/market/market_test.go`\n (`TestMarketKApp_ExecuteBuyMarket_RoyaltyReferralInflation`).",
"id": "GHSA-p7gw-2pcp-5pf8",
"modified": "2026-08-28T16:22:15Z",
"published": "2026-08-28T16:22:15Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/klever-io/klever-go/security/advisories/GHSA-p7gw-2pcp-5pf8"
},
{
"type": "WEB",
"url": "https://github.com/klever-io/klever-go/commit/8bcc600b0ac88070740c63c7ce1c8a968dd85251"
},
{
"type": "PACKAGE",
"url": "https://github.com/klever-io/klever-go"
},
{
"type": "WEB",
"url": "https://github.com/klever-io/klever-go/releases/tag/v1.7.19"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Klever: Marketplace settlement mints KLV when referral % + royalty % exceed the bid (negative seller share silently skipped)"
}
Mitigation
The most basic advice for TOCTOU vulnerabilities is to not perform a check before the use. This does not resolve the underlying issue of the execution of a function on a resource whose state and identity cannot be assured, but it does help to limit the false sense of security given by the check.
Mitigation
When the file being altered is owned by the current user and group, set the effective gid and uid to that of the current user and group when executing this statement.
Mitigation
Limit the interleaving of operations on files from multiple processes.
Mitigation
If you cannot perform operations atomically and you must share access to the resource between multiple processes or threads, then try to limit the amount of time (CPU cycles) between the check and use of the resource. This will not fix the problem, but it could make it more difficult for an attack to succeed.
Mitigation
Recheck the resource after the use call to verify that the action was taken appropriately.
Mitigation
Ensure that some environmental locking mechanism can be used to protect resources effectively.
Mitigation
Ensure that locking occurs before the check, as opposed to afterwards, such that the resource, as checked, is the same as it is when in use.
CAPEC-27: Leveraging Race Conditions via Symbolic Links
This attack leverages the use of symbolic links (Symlinks) in order to write to sensitive files. An attacker can create a Symlink link to a target file not otherwise accessible to them. When the privileged program tries to create a temporary file with the same name as the Symlink link, it will actually write to the target file pointed to by the attackers' Symlink link. If the attacker can insert malicious content in the temporary file they will be writing to the sensitive file by using the Symlink. The race occurs because the system checks if the temporary file exists, then creates the file. The attacker would typically create the Symlink during the interval between the check and the creation of the temporary file.
CAPEC-29: Leveraging Time-of-Check and Time-of-Use (TOCTOU) Race Conditions
This attack targets a race condition occurring between the time of check (state) for a resource and the time of use of a resource. A typical example is file access. The adversary can leverage a file access race condition by "running the race", meaning that they would modify the resource between the first time the target program accesses the file and the time the target program uses the file. During that period of time, the adversary could replace or modify the file, causing the application to behave unexpectedly.