From ece1b12ebfa7956432027d8b995e5ed84b7da780 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 19 Jul 2026 13:12:31 +0000 Subject: [PATCH] cmd/tsconnect/wasm: don't return non-nil net.Conn interface on dial error The NetstackDialTCP/UDP hooks returned the result of DialContextTCP/UDP directly, so on error they returned a non-nil net.Conn interface holding a nil *gonet.TCPConn or *gonet.UDPConn pointer, tripping up callers that check the interface against nil and then call Close, crashing the wasm worker. Apply the same fix that 46bdbb387 made for tailscaled and tsnet. Fixes #20529 Signed-off-by: Brad Fitzpatrick Change-Id: I4fd66bb7615ee9b2d204256a43288ed7b7a12f35 --- cmd/tsconnect/wasm/wasm_js.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index f58e4201a..480b2c6b5 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -131,10 +131,24 @@ func newIPN(jsConfig js.Value) map[string]any { return true } dialer.NetstackDialTCP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { - return ns.DialContextTCP(ctx, dst) + // Note: don't just return ns.DialContextTCP or we'll return + // *gonet.TCPConn(nil) instead of a nil interface which trips up + // callers. + tcpConn, err := ns.DialContextTCP(ctx, dst) + if err != nil { + return nil, err + } + return tcpConn, nil } dialer.NetstackDialUDP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { - return ns.DialContextUDP(ctx, dst) + // Note: don't just return ns.DialContextUDP or we'll return + // *gonet.UDPConn(nil) instead of a nil interface which trips up + // callers. + udpConn, err := ns.DialContextUDP(ctx, dst) + if err != nil { + return nil, err + } + return udpConn, nil } sys.NetstackRouter.Set(true) sys.Tun.Get().Start()