Convenience dialers default to no timeout
low swesweep-fasthttp · fasthttpproxy/http.go · FasthttpHTTPDialer · run #4
Description
FasthttpHTTPDialer and FasthttpHTTPDialerDualStack pass timeout 0, which disables explicit dial and CONNECT timeouts. Combined with an attacker-influenced proxy string, this can allow slow or unresponsive proxy behavior to stall client I/O. These constructors also inherit the nil-DialFunc issue from the timeout variants.
Triage
Not triaged.
Raw scan report for this file
`fasthttpproxy/http.go` is a small public API surface that accepts a caller-supplied `proxy` string and returns a `fasthttp.DialFunc`. The main trust boundary is the exported functions:
```go
FasthttpHTTPDialer(proxy)
FasthttpHTTPDialerTimeout(proxy, timeout)
FasthttpHTTPDialerDualStack(proxy)
FasthttpHTTPDialerDualStackTimeout(proxy, timeout)
```
In a host application, `proxy` may come from configuration, user input, an API, or a malicious file/URL. The returned `DialFunc` is later used by `fasthttp` to establish outbound connections, often through a proxy.
## Data flow
1. `proxy` is passed directly into `httpproxy.Config{HTTPProxy: proxy, HTTPSProxy: proxy}`.
2. That configuration is placed into a local `Dialer`.
3. `d.GetDialFunc(false)` is called to build the actual `fasthttp.DialFunc`.
4. The error returned by `GetDialFunc` is ignored.
5. The possibly-nil `dialFunc` is returned directly.
## Function-by-function analysis
### `FasthttpHTTPDialer`
Delegates to:
```go
FasthttpHTTPDialerTimeout(proxy, 0)
```
No direct buffer handling, integer arithmetic, goroutine creation, or unsafe code. It inherits the behavior and issues of `FasthttpHTTPDialerTimeout`. The `timeout` of `0` means no explicit dial or CONNECT timeout is configured.
### `FasthttpHTTPDialerTimeout`
This is the primary vulnerable location:
```go
dialFunc, _ := d.GetDialFunc(false)
return dialFunc
```
`GetDialFunc` explicitly returns an `error`, so it is fallible. The error is discarded. If the `proxy` string is malformed, unsupported, or otherwise cannot be turned into a usable dialer, `dialFunc` may be `nil`.
Consequences:
- A caller cannot distinguish a valid dialer from a failed configuration.
- If the returned function is invoked, it may panic as a nil function call.
- If a `fasthttp.Client` treats a nil `Dial` as “not configured”, traffic may silently fall back to direct connections, bypassing the intended proxy.
- A malicious or malformed `proxy` value can therefore cause fail-open behavior or a denial of service.
The `timeout` value is also passed directly into `Dialer.Timeout` and `Dialer.ConnectTimeout`. A zero or negative timeout may disable timeout enforcement, allowing a malicious or unresponsive proxy to stall client I/O. This is lower severity because `timeout` is usually host-controlled, but the convenience wrappers make zero the default.
### `FasthttpHTTPDialerDualStack`
Delegates to:
```go
FasthttpHTTPDialerDualStackTimeout(proxy, 0)
```
It inherits the same unchecked error, possible nil `DialFunc`, and zero-timeout behavior.
### `FasthttpHTTPDialerDualStackTimeout`
Same issue as the non-dual-stack timeout variant:
```go
dialFunc, _ := d.GetDialFunc(false)
return dialFunc
```
The only additional behavior is that it enables dual-stack dialing. It still ignores the configuration error and may return a nil `fasthttp.DialFunc`.
## Other checks
- No fixed-size stack buffers or `memcpy`-style operations.
- No integer arithmetic that can overflow into a size or index.
- No tagged unions or variant discriminators.
- No command execution, SQL construction, or `unsafe` package usage.
- No obvious goroutine leak or deadlock introduced in this file.
- The most important class of bug is unchecked fallible configuration, nil callback return, and fail-open proxy bypass.
```json
[
{
"severity": "high",
"title": "Nil DialFunc returned when proxy setup fails",
"function": "FasthttpHTTPDialerTimeout",
"description": "The error returned by d.GetDialFunc(false) is discarded. If the attacker-controlled proxy string is malformed or otherwise unsupported, dialFunc can be nil. Callers cannot detect the failure; invoking the returned fasthttp.DialFunc can panic, and if a fasthttp.Client treats a nil Dial as unset, traffic may silently bypass the intended proxy."
},
{
"severity": "high",
"title": "Nil DialFunc returned when proxy setup fails (dual-stack)",
"function": "FasthttpHTTPDialerDualStackTimeout",
"description": "The dual-stack variant has the same unchecked error and nil-return issue. A crafted proxy string can produce a nil fasthttp.DialFunc, leading to panic in callers or silent proxy bypass in fasthttp clients."
},
{
"severity": "low",
"title": "Convenience dialers default to no timeout",
"function": "FasthttpHTTPDialer",
"description": "FasthttpHTTPDialer and FasthttpHTTPDialerDualStack pass timeout 0, which disables explicit dial and CONNECT timeouts. Combined with an attacker-influenced proxy string, this can allow slow or unresponsive proxy behavior to stall client I/O. These constructors also inherit the nil-DialFunc issue from the timeout variants."
}
]
```