Updated 08:20
Go's h2c security fix armed a deadline it forgot to disarm
CVE-2026-56853 was fixed on 13 August; twenty-six hours later a reproducer showed the fix closing live connections, and three releases went out on 19 August to undo it.
A preface read with no clock
On 13 August the Go team shipped two minor releases at once. The release history entry for the newer one reads: "go1.26.6 (released 2026-08-13) includes security fixes to the go command, and the crypto/tls, encoding/asn1, encoding/xml, html/template, net, net/http, and net/url packages, as well as bug fixes to the compiler, the linker, the runtime, and the crypto/tls and os packages." The companion announcement on golang-announce was titled "Go 1.26.6 and Go 1.25.13 are released with 10 security fixes".
One of those ten is the subject here. Report GO-2026-6089 in the golang/vulndb repository summarizes it as "Apply ReadHeaderTimeout when doing unencrypted HTTP/2 check in net/http", and describes the flaw in four lines:
"When a server is configured to support unencrypted HTTP/2, it reads a few bytes from each new connection to see if they contain the HTTP/2 client preface. ReadHeaderTimeout is unexpectedly not being applied when doing this."
The report carries CVE-2026-56853, classifies it as "CWE-770: Allocation of Resources Without Limits or Throttling", and names conn.readRequest and conn.serve as the vulnerable symbols — which is to say every server entry point, from Server.Serve down. The fix is exactly what the summary says: put a deadline on the peek. Fixed versions are listed as 1.25.13, 1.26.6, and 1.27.0-rc.3.
This only bites servers that opt into h2c. The original bug, Go issue 80205, was filed under the title "net/http: enabling UnencryptedHTTP2 on Server disables first header read timeout" — turning on unencrypted HTTP/2 quietly removed the protection you thought ReadHeaderTimeout was giving you.
Twenty-six hours later
Issue 80876 was opened on 2026-08-14 at 00:18 UTC, roughly a day after the releases went out. Title: "net/http: ReadHeaderTimeout remains active after unencrypted HTTP/2 handoff". The report opens flatly: "Go 1.25.13 appears to leave the connection-level ReadHeaderTimeout deadline active after an unencrypted HTTP/2 (h2c) connection has been established. As a result, healthy HTTP/2 connections are terminated when ReadHeaderTimeout expires, even when those connections are active."
The reproducer is about forty lines: a server with SetUnencryptedHTTP2(true) and ReadHeaderTimeout: 1 * time.Second, a handler that writes two bytes, flushes, and then blocks on the request context, and a client with a three-second timeout. The two runs are the whole story.
$ go run repro.go
go=go1.25.12 elapsed=3.008s read_error=context deadline exceeded (Client.Timeout or context cancellation while reading body)
$ go run repro.go
go=go1.25.13 elapsed=1.001s read_error=unexpected EOF
On 1.25.12 the stream survives until the client gives up at three seconds. On 1.25.13 it dies at 1.001 seconds. As the report puts it: "The one-second failure corresponds exactly to ReadHeaderTimeout."
The deadline that was only conditionally cleared
The diagnosis in the issue is precise, and it is a lifecycle bug rather than a logic bug: "The new code sets a read deadline before checking for the HTTP/2 client preface. After the connection is handed to the HTTP/2 server, that deadline is only cleared when Server.ReadTimeout > 0. When ReadTimeout has its default value of zero, the deadline remains active."
That conditional is why the regression did not show up everywhere at once. A server with a non-zero ReadTimeout has code on the HTTP/2 side that resets the connection deadline after headers are read, so the stale deadline gets overwritten as a side effect. A server that sets only ReadHeaderTimeout — a common, deliberately chosen configuration for long-lived streaming, since it bounds header reads without bounding body reads — has nothing to overwrite it. The deadline stays armed on the net.Conn underneath a perfectly healthy multiplexed connection and fires once, killing every stream on it.
The two documented workarounds both work by restoring that overwrite, and both cost you the configuration you chose: set Server.ReadTimeout to a non-zero value, or set Server.ReadHeaderTimeout to zero. "Neither is ideal because it changes the server's timeout semantics."
This causes almost all h2c and custom TLS listener h2 (applying TLS on h2c) to be unusable
Fangliding, on Go issue 80876, 17 August 2026
The reported blast radius is the part worth taking seriously. The original reporter's production case: "We encountered this in a production service behind a load balancer that communicates with the Go server over h2c. Long-lived server-streaming requests began disconnecting at their ReadHeaderTimeout, causing reconnection churn." A second commenter confirmed it on 1.25.13, 1.26.6 and 1.27rc3, and noted that reverting to 1.25.12, 1.26.5 and 1.27rc2 fixed it. That version list is the tell: the regression tracks the security fix exactly.
Release-blocker, then three releases in one day
The escalation took three days. On 16 August the reporter asked for a review — "it nearly caused an outage for us, and i doubt we're the only ones" — and Go team member Sean Liao replied "tentatively marking as release blocker". On 17 August Damien Neil landed commit 9689556:
"net/http: clear ReadHeaderTimeout after accepting an unencrypted h2 conn
Fix a bug where a new unencrypted HTTP/2 connection would leave ReadHeaderTimeout set on the underlying net.Conn, causing the connection to close abruptly when the timeout expired.
Consistently clear the net.Conn's timeouts before passing a Conn off to the http2 package.
The new test is adapted from CL 815300 by Benno Moskovitz."
Note the word "consistently" — the fix removes the conditional rather than adding a second special case, and the regression test came from the reporter's own patch. Backports to 1.25, 1.26 and 1.27 were requested on 18 August and opened as issues 80926, 80927 and 80928.
They shipped on 19 August. The release history now carries three entries with that date: "go1.25.14 (released 2026-08-19) includes fixes to the net/http package", the identically worded "go1.26.7", and "go1.27.0 (released 2026-08-19)", a major release. So the fix reached general availability in Go 1.27.0 on the same day it reached the two supported minor lines.
What to check on your own servers
If you call Protocols.SetUnencryptedHTTP2(true) — or run anything that does it for you — and you are on 1.25.13, 1.26.6 or a 1.27 release candidate at rc3 or later, upgrade to 1.25.14, 1.26.7 or 1.27.0. The symptom to grep your logs for is unexpected EOF on the client side at an interval that matches ReadHeaderTimeout precisely, on connections that were doing useful work. If you never enabled unencrypted HTTP/2, neither the vulnerability nor the regression applies to you; take 1.26.6 for the other nine fixes and 1.26.7 on top of it.
Primary sources: Go release history, golang/vulndb report GO-2026-6089, Go issue 80876, commit 9689556, golang-announce security release, read 2026-08-21.