Fixes #819 — tlsx hangs indefinitely when processing large target lists (~25k+ hosts).
/claim #819
Three separate bugs cause the hang:
1. ztls tlsHandshakeWithTimeout is broken (critical)
// BEFORE: Handshake() evaluates synchronously — select can never reach ctx.Done()
select {
case <-ctx.Done():
return error // never reached while Handshake blocks
case errChan <- tlsConn.Handshake(): // blocks here forever
}
Go evaluates tlsConn.Handshake() before attempting the channel send, so the select statement can never choose ctx.Done() while the handshake is blocking on an unresponsive server.
Fix: Run Handshake() in a goroutine. On timeout, close the underlying TCP connection to unblock the goroutine (closing the zcrypto TLS conn directly would deadlock on its internal mutex).
2. ztls cipher enumeration uses context.TODO() (critical)
// BEFORE: no timeout — hangs forever if server doesn't respond
c.tlsHandshakeWithTimeout(conn, context.TODO())
Even with Bug 1 fixed, context.TODO() has no deadline, so cipher probes hang forever.
Fix: Create a timeout context from c.options.Timeout (default 10s fallback).
3. Standard TLS cipher enumeration has no timeout (critical)
// BEFORE: bare Handshake() with no context
conn.Handshake()
Fix: Use conn.HandshakeContext(ctx) with a properly timed context.
| File | Change |
|---|---|
pkg/tlsx/ztls/ztls.go |
Fix tlsHandshakeWithTimeout to run handshake in goroutine; close raw conn on timeout; add cipherHandshakeContext helper; use it in EnumerateCiphers |
pkg/tlsx/tls/tls.go |
Add cipherHandshakeContext helper; use HandshakeContext in EnumerateCiphers |
pkg/tlsx/ztls/ztls_timeout_test.go |
Test: handshake interrupted in ~500ms (not hanging); context timeout helpers |
pkg/tlsx/tls/tls_timeout_test.go |
Test: context timeout helpers for ctls path |
$ go test ./pkg/tlsx/ztls/ -run "TestTLSHandshakeWithTimeout|TestCipherHandshakeContext" -v
=== RUN TestTLSHandshakeWithTimeout_ContextCancellation
--- PASS: TestTLSHandshakeWithTimeout_ContextCancellation (0.50s)
=== RUN TestCipherHandshakeContext_UsesConfiguredTimeout
--- PASS: TestCipherHandshakeContext_UsesConfiguredTimeout (0.00s)
=== RUN TestCipherHandshakeContext_DefaultsWhenZero
--- PASS: TestCipherHandshakeContext_DefaultsWhenZero (0.00s)
PASS
$ go test ./pkg/tlsx/tls/ -run "TestCipherHandshakeContext" -v
=== RUN TestCipherHandshakeContext_UsesConfiguredTimeout
--- PASS: TestCipherHandshakeContext_UsesConfiguredTimeout (0.00s)
=== RUN TestCipherHandshakeContext_DefaultsWhenZero
--- PASS: TestCipherHandshakeContext_DefaultsWhenZero (0.00s)
PASS
go vet ./... and go build ./... pass clean.
Nenad Ilic
@nenadilic84
youssefosama3820009-commits
@youssefosama3820009-commits
ProjectDiscovery
@projectdiscovery