Bug Description
Socks5Client keeps listening for all socket data events after the SOCKS5 CONNECT handshake succeeds.
Reproducible By
import { EventEmitter } from 'node:events'
import { Socks5Client, STATES } from 'undici/lib/core/socks5-client.js'
class MockSocket extends EventEmitter {
write () {}
destroy () {}
}
const socket = new MockSocket()
const client = new Socks5Client(socket)
// Simulate the state after SOCKS5 CONNECT succeeds.
client.state = STATES.CONNECTED
// This is tunneled application data, e.g. an HTTP response chunk.
socket.emit('data', Buffer.alloc(1024))
console.log('state:', client.state)
console.log('buffer length:', client.buffer.length)
Expected Behavior
After the SOCKS5 CONNECT handshake has completed, tunneled application data should be handled only by the HTTP/TLS client using the socket.
Socks5Client should stop buffering socket data once it reaches STATES.CONNECTED, or otherwise avoid appending data in the CONNECTED state.
Logs & Screenshots
state: connected
buffer length: 1024
Environment
macOS 26.4.1
Node v24.15.0
undici v8.1.0
Bug Description
Socks5Clientkeeps listening for all socketdataevents after the SOCKS5 CONNECT handshake succeeds.Reproducible By
Expected Behavior
After the SOCKS5 CONNECT handshake has completed, tunneled application data should be handled only by the HTTP/TLS client using the socket.
Socks5Clientshould stop buffering socket data once it reachesSTATES.CONNECTED, or otherwise avoid appending data in theCONNECTEDstate.Logs & Screenshots
Environment
macOS 26.4.1
Node v24.15.0
undici v8.1.0