GHSA-w4c6-7r69-w7j9 CVE-2026-52880 GO-2026-5686
klever-go: REST API slow-header connection exhaustion via Gin Engine.Run
- Severity
- 7.5 / 10
- High · CVSS 3.1
- Exploit chance (EPSS)
- 0.49%
- Chance of exploitation in the next 30 days. Higher than 42.01% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-400 Uncontrolled Resource Consumption
- CWE-770 Allocation of Resources Without Limits or Throttling
- Fix
1.7.18- Upgrade github.com/klever-io/klever-go to this version or later
Description
Summary
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 20/20 legitimate /log probes to fail with accept: too many open files. A fixed control using the same Gin router behind an explicit http.Server with ReadHeaderTimeout, ReadTimeout, and MaxHeaderBytes retained 0 slow connections and served 20/20 probes.
This report is distinct from the P2P advisories and from my direct-message goroutine report. This finding concerns Klever-owned HTTP REST startup code (cmd/seednode/api and network/api) using Gin Engine.Run without server-level header deadlines. It does not depend on MultiDataInterceptor, Batch.Decompress, libp2p, malformed P2P messages, or direct-message goroutine spawning.
Details
Seednode REST API, latest release v1.7.17:
cmd/seednode/api/api.go:17definesStart(restAPIInterface, marshalizer).cmd/seednode/api/api.go:18createsws := gin.Default().cmd/seednode/api/api.go:23returnsws.Run(restAPIInterface).cmd/seednode/CLI.md:23documents--rest-api-interface; it says:8080binds all interfaces andoffdisables the API.
Node REST API, latest release v1.7.17:
network/api/api.go:79createsws = gin.Default().network/api/api.go:98returnsws.Run(kleverFacade.RestAPIInterface()).cmd/node/main.go:147-150documents the same--rest-api-interfaceflag and says:8080binds all interfaces.docker/README.md:56-61anddocker/README.md:67-70publish host port8080for full-node and validator Docker examples.README.md:264-268documents that the node exposes a REST API for blockchain queries and operations.
The seednode REST API source is byte-identical across v1.7.14 through v1.7.17; the captured runtime PoC was executed on v1.7.17.
Current develop commit 10bcfd50 remains affected:
network/api/api.go:98still returnsws.Run(kleverFacade.RestAPIInterface()).cmd/seednode/api/api.go:59still returnsws.Run(restAPIInterface).
Gin v1.9.1 implements Engine.Run as:
func (engine *Engine) Run(addr ...string) (err error) {
address := resolveAddress(addr)
err = http.ListenAndServe(address, engine.Handler())
return
}
In my source sweep, I did not find a production http.Server{ReadHeaderTimeout: ...} wrapper for either REST start path. The only ReadHeaderTimeout hit I found in the repository was a test helper under network/api/websocket/routes_test.go.
PoC
GitHub Private Vulnerability Reporting does not appear to allow file attachments in this form, so I am including the reproduction command and captured output inline. I can paste the full 254-line Go test patch in a reply immediately if useful.
The test starts two local child servers:
- Vulnerable: the real
cmd/seednode/api.Startpath. - Fixed control: the same Gin router served through
http.Server{ReadHeaderTimeout: 250ms, ReadTimeout: 250ms, MaxHeaderBytes: 4096}.
Reproduction from a clean checkout:
git clone https://github.com/klever-io/klever-go
cd klever-go
git checkout v1.7.17
# Apply the PoC patch to cmd/seednode/api.
# I can provide the full patch in this advisory thread.
go test ./cmd/seednode/api -run TestPoC_SeednodeAPISlowlorisDifferential -count=1 -v -timeout 60s
Captured output on v1.7.17:
POC_RESULT mode=vulnerable slow_connections_opened=120 slow_connections_still_open=111 legitimate_probe_ok=0 legitimate_probe_fail=20
POC_RESULT mode=fixed slow_connections_opened=120 slow_connections_still_open=0 legitimate_probe_ok=20 legitimate_probe_fail=0
The vulnerable server also logs repeated accept failures:
http: Accept error: accept tcp 127.0.0.1:56415: accept: too many open files; retrying in 1s
Impact
For an externally reachable Klever REST listener, a single unauthenticated client can retain many server-side connections by never completing HTTP headers. Because the Go server has no read-header deadline, those connections persist until the client closes them or an external proxy/firewall intervenes.
The direct result is REST API unavailability for legitimate clients. The local proof demonstrates this as 0/20 legitimate /log probes succeeding while the vulnerable server is saturated, versus 20/20 succeeding with the fixed server wrapper.
I am not claiming default public internet exposure. The default bind is localhost:8080. The affected condition is a REST API listener exposed through Klever's documented all-interface bind or Docker port-publish deployment shape.
This maps to the SECURITY.md High category: "Denial of Service affecting network availability." If Klever treats externally reachable REST API unavailability as non-critical because the default bind is localhost, the conservative classification is Medium under "Performance degradation attacks" / "Non-critical DoS vectors."
All testing was local loopback only. I did not contact Klever mainnet, public testnet, hosted RPCs, explorers, or third-party production infrastructure.
Suggested fix:
Start both REST APIs through explicit http.Server values instead of Engine.Run, for example:
srv := &http.Server{
Addr: restAPIInterface,
Handler: ws.Handler(),
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 32 << 10,
}
return srv.ListenAndServe()
Apply the same pattern to:
cmd/seednode/api.Startnetwork/api.Start
If Klever expects deployments to expose the REST API through a reverse proxy, I still recommend setting server-level limits in the application. That keeps the binary safe when operators use the documented direct bind or Docker port-publish path.
Affected versions
Go
| Package | Vulnerable | Fixed in |
|---|---|---|
| github.com/klever-io/klever-go | >= 1.7.14, < 1.7.18 |
1.7.18 |
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.18
- go
go get github.com/klever-io/klever-go@v1.7.18 && 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-400: Uncontrolled Resource Consumption
The product does not properly control the allocation and maintenance of a limited resource.
How to prevent it
- 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. 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.
- 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, or 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 is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
- Architecture and Design: Ensure that protocols have specific limits of scale placed on them.
- Implementation: Ensure that all failures in resource allocation place the system into a safe posture.
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-4fwh-wrm6-97xm Klever-Go: Unauthenticated WebSocket /subscribe: no read-size limit, no connection cap, permissive origin -> remote node memory/goroutine exhaustion (DoS) | 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 |
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