siyuan-note/siyuan · error
proxy returned unexpected tunnel data
Error message
proxy returned unexpected tunnel data
What it means
In this SSRF-safe transport's RoundTrip, after the proxy answers CONNECT for an https target, the code checks that the proxy sent exactly the tunnel establishment bytes: any buffered residue means the proxy injected or pipelined data into the tunnel before TLS began. The connection is closed because proceeding could leak or corrupt the TLS stream (e.g. a MITM proxy that already spoke plaintext).
Source
Thrown at kernel/util/httprequest.go:109
return nil, err
}
if proxyURL == nil {
return t.directTransport.RoundTrip(req)
}
targetAddr, err := t.resolvePublicTarget(req.Context(), req.URL)
if err != nil {
return nil, err
}
conn, reader, err := dialProxyTunnel(req.Context(), proxyURL, targetAddr)
if err != nil {
return nil, err
}
if req.URL.Scheme == "https" {
if reader.Buffered() != 0 {
conn.Close()
return nil, errors.New("proxy returned unexpected tunnel data")
}
tlsConn := tls.Client(conn, &tls.Config{ServerName: req.URL.Hostname(), NextProtos: []string{"http/1.1"}})
if err = tlsConn.HandshakeContext(req.Context()); err != nil {
conn.Close()
return nil, err
}
conn = tlsConn
reader = bufio.NewReader(conn)
}
targetReq := req.Clone(req.Context())
targetReq.URL = cloneURL(req.URL)
targetReq.URL.Scheme = ""
targetReq.URL.Host = ""
targetReq.RequestURI = ""
targetReq.Header.Del("Proxy-Authorization")
if targetReq.Host == "" {
targetReq.Host = req.URL.HostView on GitHub (pinned to 8641553a1f)
Solutions
- Inspect/replace the HTTP proxy configured for the agent client — use a standards-compliant proxy that sends only the CONNECT response with no residual bytes
- Test the proxy with 'curl -x proxy https://target' to see if it injects data; update or bypass the intercepting proxy for this traffic
- If the target can be reached directly, remove the proxy setting so RoundTrip uses the direct SSRF-validated connection
Example fix
// before: intercepting proxy injects bytes after CONNECT HTTPS_PROXY=http://corporate-mitm:8080 // after: allowlist the target on the proxy or connect directly HTTPS_PROXY=
Defensive patterns
Strategy: fallback
Try / catch
if err := client.Do(req); err != nil {
if strings.Contains(err.Error(), "proxy returned unexpected tunnel data") {
return directFallback(req) // retry without the proxy
}
return err
} Prevention
- Use standards-compliant proxies; test that CONNECT responses carry no extra bytes
- Keep an allowlist so trusted targets can bypass intercepting middleboxes
- Monitor for this error after corporate proxy upgrades
When it happens
Trigger: RoundTrip routes an https request through ssrfSafeClient's proxy path; after reading the CONNECT response, bufio reader has leftover bytes (proxy sent 200 followed by extra data, or responded non-protocol data).
Common situations: Corporate/intercepting proxies (Zscaler, squid with injected headers) that append data after the CONNECT response; misbehaving custom forward proxies; a proxy answering CONNECT with an error page plus keep-alive residue.
Related errors
- download failed: %s
- SOCKS5 proxy does not support context dialing
- proxy CONNECT returned %s
- system proxy does not contain a supported HTTP, HTTPS or SOC
- unsupported system proxy protocol [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d49d49a64ddd04c5.
Report an issue: GitHub.