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)