fix: self-connect fd leak, udp callback panic, and mTLS that does not verify clients (#123, #125, #127) - #145
Conversation
…g the process, and verify mTLS clients Three findings from code review, all in the accept / TLS paths. AlexStocks#123 server.accept() detected a self-connect, logged it and returned without closing the connection it had just accepted. The accept loop simply continues, so that descriptor leaked for the life of the process. The client side already closes before it reports errSelfConnect. AlexStocks#125 (two of its three items; the WSS Serve panic was already gone from master) - a udp endpoint's newSession callback returning an error panicked inside the goroutine RunEventLoop spawned, and nothing can recover a panic there, so a transient error in a user callback killed the process. It now logs and stops serving, like the tcp accept path does. - sslEnabled without a tlsConfigBuilder reached dialTCP, which runs inside the reconnect goroutine, turning a configuration mistake into a nil-pointer panic reported from somewhere else entirely. newClient rejects that combination up front, naming the option that is missing. AlexStocks#127 with a trust collection configured, ServerTlsConfigBuilder still asked for a client certificate with RequireAnyClientCert - which demands a certificate but verifies nothing - so ClientCAs was dead configuration and any self-signed certificate completed the handshake. It now requires and verifies against the collection, the way the WSS server path already did, and the server config gets the TLS 1.2 floor the client builder has always had. Five regression tests, every one of them failing on master: TestAcceptClosesSelfConnect accept() left the self-connect connection open: the fd is leaked TestUDPNewSessionErrorDoesNotPanic panic: callback failed (the goroutine panic took the test binary down) TestNewClientSSLRequiresTLSConfigBuilder NewTCPClient(sslEnabled, no tlsConfigBuilder) did not panic TestServerTLSConfigBuilderVerifiesClientCertificate ClientAuth = RequireAnyClientCert, want RequireAndVerifyClientCert TestServerTLSConfigBuilderWithoutTrustCollection MinVersion = 0, want TLS 1.2
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe transport layer now validates missing TLS client builders, closes self-connect connections, handles UDP session errors without panics, and enforces stronger server TLS settings. Regression tests cover each behavior. ChangesTransport reliability and TLS security
Priority: ⬆️ High Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix · Severity of issue fixed: High Suggested reviewers: Merge Risk: ⚪ Minimal · up to The transport fixes and TLS hardening changes are covered by regression tests, with no concrete unresolved merge risk identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes #123. Fixes #125. Fixes #127.
Three code-review findings, all small, all silent from the caller's side, each with a regression test that fails on master.
#123
server.accept()leaked the fd of a self-connectThe connection had already been accepted, so it owns a descriptor; the accept loop just continues, and that descriptor leaks for the life of the process. The client side closes before reporting
errSelfConnect; the server side now does too.#125 two of the three process-killing panics
udp endpoint,
newSessioncallback error (runUDPEventLoop):A panic in a goroutine the library started cannot be recovered by any caller, so a transient error in a user callback (dependency not ready, validation failure) took the process down. It now logs and stops serving, which is what the tcp accept path does.
client with
sslEnabledand notlsConfigBuilder:dialTCPcallsc.tlsConfigBuilder.BuildTlsConfig(), anddialTCPruns inside the reconnect goroutine.newClientonly validatednumber/addr, so the combination surfaced as a nil-pointer panic from an unrelated place. It is now rejected innewClient, synchronously, before anything is started:#127 mTLS was configuration theatre
crypto/tlsonly consultsClientCAsfromVerifyClientCertIfGivenupwards, so with a trust collection configuredcertPoolwas dead configuration: any self-signed certificate completed the handshake. It is nowtls.RequireAndVerifyClientCert, which is what the WSS server path already used. The same builder also leftMinVersionat 0 while the client builder has always set TLS 1.2, so the server accepted TLS 1.0/1.1; that is fixed too.Tests
All five fail on master:
go test ./transport -race,make test,make check-fmtandmake lintare green on this branch.Summary by CodeRabbit