From 721194dfb5a5dee12510891b66b61666d8515310 Mon Sep 17 00:00:00 2001 From: Codinget Date: Sun, 12 Jul 2026 11:28:33 +0000 Subject: [PATCH] fix(tsconnect/wasm): close conn on upgradeTLS configuration errors too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously only a handshake failure closed the underlying conn; configuration errors (malformed caCerts PEM, bad cert/key pair) returned with the conn still open, while the JS wrapper treats every upgradeTLS rejection as fatal and marks the conn closed — leaking a live Go conn that could no longer be closed from JS. Close on every error path so the JS contract (any rejection after validation is fatal) holds. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH --- cmd/tsconnect/wasm/wasm_js.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index eaff7836b..bfae237ad 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -1482,9 +1482,11 @@ func wrapConn(conn net.Conn) map[string]any { }), // upgradeTLS wraps the conn in TLS in place (STARTTLS-style) and // returns a new wrapped conn sharing the same underlying net.Conn; - // the old handle must not be used afterward. On handshake failure - // the underlying conn is closed. With isServer, certPem and keyPem - // are required; otherwise client options as in dialTLS apply. + // the old handle must not be used afterward. On any failure — + // configuration or handshake — the underlying conn is closed, so + // callers can treat every rejection as fatal to the connection. + // With isServer, certPem and keyPem are required; otherwise client + // options as in dialTLS apply. "upgradeTLS": js.FuncOf(func(this js.Value, args []js.Value) any { opts := js.Undefined() if len(args) > 0 { @@ -1497,16 +1499,19 @@ func wrapConn(conn net.Conn) map[string]any { certPem := opts.Get("certPem") keyPem := opts.Get("keyPem") if certPem.Type() != js.TypeString || keyPem.Type() != js.TypeString { + conn.Close() return nil, fmt.Errorf("upgradeTLS: certPem and keyPem are required when isServer is set") } cert, err := tls.X509KeyPair([]byte(certPem.String()), []byte(keyPem.String())) if err != nil { + conn.Close() return nil, fmt.Errorf("upgradeTLS: parsing cert/key: %w", err) } tlsConn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}}) } else { cfg, err := tlsClientConfigFromJS("", opts) if err != nil { + conn.Close() return nil, err } tlsConn = tls.Client(conn, cfg)