valyala/fasthttp · error
proxy dial target address contains cr or lf: %q
Error message
proxy dial target address contains cr or lf: %q
What it means
httpProxyDial validates the target address before building the CONNECT request through an HTTP proxy. Addresses containing CR or LF would enable request-splitting/header injection in the proxy request, so dialing is refused with this error.
Source
Thrown at fasthttpproxy/dialer.go:229
// In the httpProxyDial function, the proxy.Dialer that implements
// this interface can retrieve timeout information when sending the CONNECT
// method to the HTTP proxy.
type httpProxyDialer interface {
connectTimeout() time.Duration
}
// DialerFunc Make a function of type func(network, addr string) (net.Conn, error)
// implement the proxy.Dialer interface.
type DialerFunc func(network, addr string) (net.Conn, error)
func (d DialerFunc) Dial(network, addr string) (net.Conn, error) {
return d(network, addr)
}
// Establish a connection through an HTTP proxy.
func httpProxyDial(dialer proxy.Dialer, network, addr, proxyAddr, auth string) (net.Conn, error) {
if strings.ContainsAny(addr, "\r\n") {
return nil, fmt.Errorf("proxy dial target address contains cr or lf: %q", addr)
}
conn, err := dialer.Dial(network, proxyAddr)
if err != nil {
return nil, err
}
var connectTimeout time.Duration
hp, ok := dialer.(httpProxyDialer)
if ok {
connectTimeout = hp.connectTimeout()
}
if connectTimeout > 0 {
if err = conn.SetDeadline(time.Now().Add(connectTimeout)); err != nil {
_ = conn.Close()
return nil, err
}
defer func() {View on GitHub (pinned to c96f600972)
Solutions
- Sanitize the target host: strip/reject any control characters before dialing
- Parse the URL with net/url and use only u.Host, which normalizes out CR/LF
- Reject the request at the application layer with a 400-style response when the host contains \r or \n
- Log the rejected address for security monitoring
Example fix
// before
dialer.Dial("tcp", rawHostFromUser) // rawHostFromUser = "evil.com:80\r\nX: y"
// after
u, err := url.Parse("http://" + rawHostFromUser)
if err != nil || strings.ContainsAny(u.Host, "\r\n") {
return fmt.Errorf("invalid proxy target host: %q", rawHostFromUser)
}
dialer.Dial("tcp", u.Host) Defensive patterns
Strategy: validation
Validate before calling
if strings.ContainsAny(targetAddr, "\r\n") {
return errors.New("target address must not contain CR or LF")
} Type guard
func isSafeProxyTarget(addr string) bool {
u, err := url.Parse("http://" + addr)
return err == nil && u.Host == addr && !strings.ContainsAny(addr, "\r\n\x00")
} Try / catch
conn, err := proxyDialer.Dial("tcp", addr)
if err != nil {
if strings.Contains(err.Error(), "contains cr or lf") {
return fmt.Errorf("rejected unsafe proxy target: %q", addr)
}
return err
} Prevention
- Parse user-supplied URLs with net/url and use u.Host only
- Reject control characters in hosts at the edge (server-side request validation)
- Treat CRLF-in-host input as a potential SSRF/injection attack and log it
When it happens
Trigger: Calling (&fasthttpproxy.HttpProxyDialer{...}).Dial (or ProxyDialer) with an addr like "example.com:80\r\nX-Evil: 1", typically from unsanitized user input or a malicious URL host.
Common situations: Proxying URLs built from raw user input, CRLF injection attempts from untrusted clients, Host headers copied verbatim from inbound requests.
Related errors
- must implement readat
- directory index required
- no 'create file' permissions
- seek is not implemented
- fasthttp: contain forbidden trailer
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/66886df85df75aa0.
Report an issue: GitHub.