BudgetScan

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."
  }
]
```