feat(tsconnect/wasm): add upgradeTLS to wrapped conns #14
No Reviewers
Labels
Clear labels
Agentic
Component/CI
Component/Funnel
Component/React
Component/State
Component/Taildrive
Component/Taildrop
Component/Tailscale
Component/Tailshare
Component/Transport
Component/tsconnect
Component/VFS
Component/WebRTC
Component/Worker
Human
Protocol/FTP
Protocol/HTTP
Protocol/SFTP
Protocol/SMB
Protocol/SSH
Protocol/WebDAV
Protocol/WebSocket
Security
Agent
claude-fable-5
Work done by Claude Fable 5
Agent
claude-opus-4-8
Work done by Claude Opus 4.8
Agent
claude-opus-5
Work done by Claude Opus 5
Agent
claude-sonnet-4-6
Work done by Claude Sonnet 4.6
Agent
claude-sonnet-5
Work done by Claude Sonnet 5
Agent
gpt-5.5
Work done by GPT 5.5
Agent
gpt-5.6-luna
Work done by GPT 5.6 Luna
Agent
gpt-5.6-sol
Work done by GPT 5.6 Sol
Agent
gpt-5.6-terra
Work done by GPT 5.6 Terra
Opened by an agent
Work on the CI tooling
Work on the Tailscale Funnel or certificate system
Work on a React binding
Work on a state store (eg Redux)
Work on the taildrive system
Work on the taildrop system
Work on the Tailscale fork
Work on the Tailshare app
Work on the transport system
Work on the tsconnect packages
Work on the VFS system
Work on the WebRTC system
Work on the worker system
Opened by a human
Kind
Bug
Bug work
Kind
Enhancement
Enhancement work
Kind
Feature
Feature work
Kind
Maintenance
Maintenance work
Priority
P0
1
Critical work that must be done right now
Priority
P1
2
Urgent work
Priority
P2
3
Medium priority work
Priority
P3
4
Low priority work
Priority
P4
5
Lowest priority work, wishlist-tier
Work on the FTP protocol
Work on the HTTP protocol
Work on the SFTP protocol
Work on the SMB protocol
Work on the SSH protocol
Work on the WebDAV protocol
Work on the WebSocket protocol
Security work
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: webnet/tailscale#14
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Adds an
upgradeTLSmethod to the conn objects returned bydial/accept, wrapping the existingnet.Connwithcrypto/tlsin place — the explicit upgrade needed for STARTTLS (SMTP) and AUTH TLS (FTPS).tlsClientConfigFromJSfactored out ofdialTLS(behavior unchanged); when no default server name is available (the upgrade case) it requiresserverNameunlessinsecureSkipVerifyis set.upgradeTLS(opts)on wrapped conns: client mode uses the same options asdialTLS(serverName,insecureSkipVerify,caCerts); server mode viaisServer: truewithcertPem/keyPem(same parsing aslistenTLS).net.Conn; the old handle must not be used afterward. On any failure — configuration (malformed PEM) or handshake — the underlying conn is closed (721194d, after external review: previously config errors left the conn open while the JS wrapper marked it closed, leaking it).Consumed by the corresponding
@webnet/transport/@webnet/tsconnectPR on the webnet repo (webnet/webnet#63), which provides the in-placeRawTransport.upgradeTlssemantics one layer up.Reviewed alongside webnet/webnet#63 (the consumer of upgradeTLS). The Go side here looks correct in isolation, but flagging for context: the new
wrapConn(tlsConn)returned byupgradeTLS(around line 1484 in cmd/tsconnect/wasm/wasm_js.go) leaves the old wrapConn's read/write closures alive, still bound to the plainnet.Connthattls.Client/tls.Servernow uses internally. That's fine as long as the JS caller strictly stops using the old handle the instant it calls upgradeTLS — but webnet/webnet#63'sipn.ts Conn.upgradeTlsdoesn't actually enforce that (it doesn't mark itself in-flight during the handshake), so a concurrent read()/write() from the JS side can still reach the old handle and race the handshake on the same fd. Posted the detailed finding and suggested fix on webnet#63; no action needed here unless you want to harden this side too (e.g. by having the old wrapConn's closures start erroring once superseded).