Skip to content

fix(sei-tendermint): add ReadHeaderTimeout to CometBFT RPC HTTP server (PLT-440)#3607

Open
amir-deris wants to merge 3 commits into
mainfrom
amir/plt-440-rpc-server-read-header-timeout
Open

fix(sei-tendermint): add ReadHeaderTimeout to CometBFT RPC HTTP server (PLT-440)#3607
amir-deris wants to merge 3 commits into
mainfrom
amir/plt-440-rpc-server-read-header-timeout

Conversation

@amir-deris

@amir-deris amir-deris commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • ReadHeaderTimeout was absent from the CometBFT JSON-RPC HTTP server, leaving it vulnerable to slowloris attacks: a client could hold a connection open indefinitely by sending HTTP headers one byte at a time.
  • ReadHeaderTimeout is now 10s by default, enforced on the main RPC server (:26657) as well as the light-client proxy and inspect RPC paths.
  • Exposed as timeout-read-header in RPCConfig and the generated config.toml so operators can tune it.
  • ValidateBasic rejects negative values, matching the existing timeout-write validation pattern.

Completes PLT-440 alongside #3558 (which added WriteTimeout).

Changes

File Change
sei-tendermint/rpc/jsonrpc/server/http_server.go Added ReadHeaderTimeout field to Config; default 10s; wired into Serve() and ServeTLS()
sei-tendermint/config/config.go Added TimeoutReadHeader field to RPCConfig; default 10s; ValidateBasic rejects negative values
sei-tendermint/internal/rpc/core/env.go Assigns conf.RPC.TimeoutReadHeadercfg.ReadHeaderTimeout
sei-tendermint/cmd/tendermint/commands/light.go Same for the light-client RPC proxy
sei-tendermint/internal/inspect/rpc/rpc.go Same for the inspect RPC server
sei-tendermint/config/toml.go Added timeout-read-header template entry
sei-tendermint/config/config_test.go Added "TimeoutReadHeader" to TestRPCConfigValidateBasic field sweep
sei-tendermint/rpc/jsonrpc/server/http_server_test.go Added TestReadHeaderTimeoutSlowloris: opens a raw TCP connection with incomplete headers and asserts the server closes or 408s within the timeout window

Risk

The 10s default is consistent with the existing timeout-read default and is well above any legitimate header round-trip on Sei.

Note on 0s semantics: setting timeout-read-header = "0s" does not disable the timeout. Per Go's net/http, a zero ReadHeaderTimeout falls back to ReadTimeout — which is fixed at 10s in this stack due to an existing > 0 guard in env.go that prevents operators from zeroing it out via config. In practice, ReadHeaderTimeout is always at minimum 10s regardless of what timeout-read-header is set to.

🤖 Generated with Claude Code

@amir-deris amir-deris self-assigned this Jun 17, 2026
@amir-deris amir-deris changed the title Added read header timeout fix(sei-tendermint): add ReadHeaderTimeout to CometBFT RPC HTTP server (PLT-440) Jun 17, 2026
@cursor

cursor Bot commented Jun 17, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Low risk: defensive HTTP hardening with a conservative default; main operational impact is cutting off clients that stall on headers, which is intended.

Overview
Adds HTTP request header read timeouts across CometBFT JSON-RPC so connections cannot be held open indefinitely by incomplete headers (slowloris).

Configuration: New RPCConfig.TimeoutReadHeader / timeout-read-header in config.toml, default 10s, with negative values rejected in ValidateBasic and included in config tests.

Server wiring: ReadHeaderTimeout is added to the JSON-RPC server.Config defaults and applied in Serve / ServeTLS. It is propagated from node config into the main RPC service (env.go), the light-client proxy (light.go), and the inspect RPC path (inspect/rpc/rpc.go).

Tests: TestReadHeaderTimeoutSlowloris sends partial headers on a raw TCP connection and asserts the server closes or returns 408 within the timeout window.

Reviewed by Cursor Bugbot for commit 310f12a. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJun 17, 2026, 11:12 PM

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7c228d7. Configure here.

Comment thread sei-tendermint/rpc/jsonrpc/server/http_server_test.go
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 58.14%. Comparing base (8d59181) to head (310f12a).

Files with missing lines Patch % Lines
sei-tendermint/cmd/tendermint/commands/light.go 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3607      +/-   ##
==========================================
- Coverage   59.02%   58.14%   -0.88%     
==========================================
  Files        2215     2141      -74     
  Lines      182513   173975    -8538     
==========================================
- Hits       107720   101155    -6565     
+ Misses      65101    63828    -1273     
+ Partials     9692     8992     -700     
Flag Coverage Δ
sei-chain-pr 50.79% <94.73%> (?)
sei-db 70.41% <ø> (ø)
sei-db-state-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
sei-tendermint/config/config.go 73.68% <100.00%> (+0.16%) ⬆️
sei-tendermint/config/toml.go 55.00% <ø> (ø)
sei-tendermint/internal/inspect/rpc/rpc.go 62.12% <100.00%> (+0.58%) ⬆️
sei-tendermint/internal/rpc/core/env.go 78.36% <100.00%> (+0.12%) ⬆️
sei-tendermint/rpc/jsonrpc/server/http_server.go 68.58% <100.00%> (+0.61%) ⬆️
sei-tendermint/cmd/tendermint/commands/light.go 42.46% <0.00%> (-0.30%) ⬇️

... and 74 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…lowloris

If the 500ms read deadline fires before the server closes the connection,
conn.Read returns a net.Timeout error — previously the test exited with no
assertion, silently passing even if ReadHeaderTimeout never fired.

Now errors.As detects the timeout case and calls t.Fatal, making the false-
pass explicit. EOF or connection-reset remains the expected happy path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants