CVE-2026-47208
JavaScript 취약성 분석 및 완화

개요

CVE-2026-47208 is a sandbox breakout vulnerability in the vm2 Node.js sandboxing library, classified as "Sandbox Breakout Through Promise Species." It affects all versions of vm2 up to and including 3.11.3, and was published on May 18, 2026 by the maintainer, with the GitHub Advisory Database entry added May 29, 2026. The flaw allows attackers who can execute arbitrary code inside a vm2 sandbox to escape the sandbox and run arbitrary commands on the host system. It carries a CVSS v3.1 base score of 10.0 (Critical) (GitHub Advisory, vm2 Advisory).

기술적 세부 사항

The root cause (CWE-913: Improper Control of Dynamically-Managed Code Resources) lies in the localPromise constructor in lib/setup-sandbox.js. When attaching an internal "swallow tail" to silence unhandled rejections, the constructor calls the cached host Promise.prototype.then via apply(globalPromisePrototypeThen, this, [undefined, localPromiseSwallow]) without first invoking resetPromiseSpecies(this). Every other call site in vm2 that touches a host then/catch already bookends with resetPromiseSpecies, but this constructor-body call was the sole omission. Because the host then uses the ECMAScript species protocol — reading this.constructor[Symbol.species] and calling Construct with it — a sandbox subclass can override Symbol.species to redirect the downstream child constructor to a user-controlled function, which then receives V8's internal (resolve, reject) capability. Combined with a binary-searched deep-recursion primitive to surface a host-realm RangeError (via e.stack), the raw host error bypasses all sandbox sanitizers and lands in the attacker's collector; from there, ex.constructor.constructor("return process")() yields the host Function constructor and full RCE. A working proof-of-concept is publicly included in the advisory (GitHub Advisory, vm2 Commit).

영향

Successful exploitation grants an attacker full remote code execution on the host system with the privileges of the process running vm2, completely breaking the sandbox isolation guarantee. All three security dimensions are maximally impacted: confidentiality (full host data access), integrity (arbitrary file and system modification), and availability (ability to crash or disrupt the host process). Any application that accepts untrusted JavaScript and executes it inside a vm2 sandbox — such as online code execution platforms, plugin systems, or multi-tenant Node.js services — is at risk of complete host compromise, including lateral movement to other systems reachable from the host (GitHub Advisory, vm2 Advisory).

착취 단계

  1. Identify target: Locate an application that accepts untrusted JavaScript and executes it inside a vm2 sandbox (version ≤ 3.11.3), such as a code execution API, plugin runner, or online REPL.
  2. Declare a malicious Promise subclass: Inside the sandbox, define class FakePromise extends Promise { static get [Symbol.species]() { return ct; } } where ct is a user-controlled variable.
  3. Set up the species hijack: Define ct = function(executor) { executor(userResolve, userReject); } so that when V8 calls Construct(ct, [internalExecutor]), the sandbox-controlled userReject becomes V8's internal reject function for the swallow-tail child.
  4. Trigger the swallow tail: Call new FakePromise(r => r()). This enters localPromise's constructor, which calls apply(globalPromisePrototypeThen, this, [undefined, localPromiseSwallow]) without resetting the species — V8 reads FakePromise[Symbol.species]ct → constructs the child via ct, binding userReject as V8's internal reject.
  5. Surface a host-realm error: Use a binary-searched deep recursion function (function so(d) { if (d > 0) so(d-1); const e = new E(); e.stack; throw e; }) to find the stack depth at which V8 raises a host-realm RangeError inside PromiseResolveThenableJob. V8 delivers this raw host error to userReject, bypassing all sandbox sanitizers.
  6. Achieve RCE: Read ex.constructor.constructor("return process")() on the captured host-realm error to obtain the host Function constructor and process object, then call process.mainModule.require('child_process').execSync('touch pwned') (or any arbitrary command) (GitHub Advisory, vm2 Commit).

타협의 징후

  • Logs: Node.js application logs showing unexpected execution of system commands (e.g., execSync, spawnSync) originating from within a vm2 sandbox context; error logs containing host-realm RangeError stack traces with unusual recursion depths.
  • File System: Unexpected files created on the host (e.g., a file named pwned in the working directory, as demonstrated in the PoC); new scripts, cron jobs, or binaries written by the Node.js process user.
  • Process: Unusual child processes spawned by the Node.js process (e.g., sh, bash, curl, wget, python) that are not part of normal application behavior; child_process.execSync or spawnSync calls visible in process audit logs.
  • Network: Unexpected outbound connections from the Node.js server to external IPs, particularly reverse shell connections or data exfiltration traffic, initiated by the vm2 host process.
  • Code Patterns (Detection): Sandbox input containing Symbol.species, FakePromise, class.*extends Promise, or constructor.constructor patterns combined with deep recursion functions — these are indicators of attempted species hijack exploitation (vm2 Commit).

완화 및 해결 방법

The primary remediation is to upgrade vm2 to version 3.11.4, which adds a single resetPromiseSpecies(this) call immediately before the swallow-tail apply(globalPromisePrototypeThen, this, [undefined, localPromiseSwallow]) in lib/setup-sandbox.js, closing the species hijack channel (vm2 Release, vm2 Commit). Version 3.11.4 also patches nine other security advisories in the same release. If immediate patching is not possible, restrict network access to services running vulnerable vm2 instances, minimize the OS privileges of the Node.js process (e.g., run as a low-privilege user, use seccomp/AppArmor), and consider blocking or sanitizing sandbox inputs containing Symbol.species overrides or deep recursion patterns as a defense-in-depth measure (GitHub Advisory).

커뮤니티 반응

Coverage of this vulnerability appeared in security news outlets including Heise (reporting on four critical vm2 vulnerabilities with maximum CVSS ratings) and SecurityOnline.info (covering vm2 sandbox escape vulnerabilities enabling Node.js RCE), as well as BeyondMachines threat intelligence summaries (Heise, SecurityOnline). The vulnerability was reported by researcher XmiliaH, credited in the official advisory (vm2 Advisory). The release of a complete, functional PoC alongside the advisory drew attention to the ease of exploitation for any attacker with sandbox code execution access.

추가 자료


근원이 보고서는 AI를 사용하여 생성되었습니다.

관련 JavaScript 취약점:

CVE ID

심각도

점수

기술

구성 요소 이름

CISA KEV 익스플로잇

수정 사항이 있습니다.

게시된 날짜

CVE-2026-54157CRITICAL9
  • JavaScriptJavaScript
  • @lobehub/lobehub
아니요Jun 16, 2026
CVE-2026-42089HIGH8.6
  • JavaScriptJavaScript
  • yeoman-environment
아니요Jun 16, 2026
CVE-2026-47684HIGH7.7
  • JavaScriptJavaScript
  • @sync-in/server
아니요Jun 16, 2026
CVE-2026-54298MEDIUM4.2
  • JavaScriptJavaScript
  • astro
아니요Jun 16, 2026
CVE-2026-54326LOW2.5
  • JavaScriptJavaScript
  • @earendil-works/pi-coding-agent
아니요Jun 16, 2026

무료 취약성 평가

클라우드 보안 태세를 벤치마킹합니다

9개의 보안 도메인에서 클라우드 보안 관행을 평가하여 위험 수준을 벤치마킹하고 방어의 허점을 식별합니다.

평가 요청

추가 Wiz 리소스

맞춤형 데모 받기

맞춤형 데모 신청하기

"내가 본 최고의 사용자 경험은 클라우드 워크로드에 대한 완전한 가시성을 제공합니다."
데이비드 에슬릭최고정보책임자(CISO)
"Wiz는 클라우드 환경에서 무슨 일이 일어나고 있는지 볼 수 있는 단일 창을 제공합니다."
아담 플레처최고 보안 책임자(CSO)
"우리는 Wiz가 무언가를 중요한 것으로 식별하면 실제로 중요하다는 것을 알고 있습니다."
그렉 포니아토프스키위협 및 취약성 관리 책임자