CVE-2026-32731: 
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-32731 is a Zip Slip / Path Traversal vulnerability (CWE-22) in the @apostrophecms/import-export module of ApostropheCMS, an open-source content management framework. It affects all versions up to and including 3.5.2 of the @apostrophecms/import-export npm package. The vulnerability was reported on 2026-03-08 and publicly disclosed on 2026-03-18, with a patch released the same day in version 3.5.3. It carries a CVSS v3.1 base score of 9.9 (Critical) (GitHub Advisory, ApostropheCMS Advisory).

Technical details

The root cause is in the extract() function within packages/import-export/lib/formats/gzip.js (lines ~132–157), which constructs file-write paths using fs.createWriteStream(path.join(exportPath, header.name)). Node.js's path.join() does not resolve or sanitize path traversal segments such as ../; it concatenates them as-is, so a tar entry named ../../evil.js resolves to a path outside the intended extraction directory. No canonical-path check is performed before the write stream is opened, making this a textbook Zip Slip attack (CWE-22). An attacker with the "Global Content Modify" permission — a standard editor-level role — can craft a malicious .tar.gz archive containing traversal-named entries and upload it via the standard CMS import UI to write arbitrary content anywhere the Node.js process has filesystem access (ApostropheCMS Advisory, GitHub Advisory).

Impact

Successful exploitation enables arbitrary file write to any path accessible by the Node.js process, with a full impact chain that includes: site defacement and stored XSS by writing files to the CMS public/ directory served via Express static middleware; persistent remote code execution (RCE) by overwriting Node.js startup files (e.g., module index.js, config files, route files) that execute on the next server restart — which in containerized environments occurs automatically; credential and secret exfiltration by overwriting .env or app.config.js; and denial of service by corrupting critical application files such as package.json. The scope is changed (S:C), with high confidentiality, integrity, and availability impact (ApostropheCMS Advisory).

Exploitability

A proof-of-concept exploit with detailed step-by-step reproduction instructions (including specific commands, payloads, and a video PoC) is publicly available in the official security advisory. A separate Python PoC tool (exp.py) also exists in a public GitHub repository (0xEr3n/CVE-2026-32731). Exploitation requires only a low-privilege authenticated account with the "Global Content Modify" permission, which is routinely granted to content editors and site managers. The EPSS score is approximately 0.063–0.099%, and there is no current evidence of in-the-wild exploitation or CISA KEV catalog listing (ApostropheCMS Advisory, GitHub Advisory).

Exploitation steps

  1. Obtain credentials: Acquire any CMS account with the "Global Content Modify" permission (standard content editor or site manager role).
  2. Create the payload file: Prepare the file content to be written to the server. For a stored XSS/defacement attack:
    echo "alert('XSS')" > payload.html
  3. Generate the malicious archive: Use the provided Python tool (make-slip-tar.py) to craft a .tar.gz with a traversal-named entry targeting the CMS public/ directory (adjust ../ depth based on the server's temp directory location relative to the project root — typically 2–4 levels):
    python make-slip-tar.py payload.html "../../../../public/injected.html"
    This produces evil-slip.tar.gz containing the required aposDocs.json and aposAttachments.json stubs plus the traversal payload entry.
  4. Upload via CMS Import UI: Log in to the CMS, navigate to Global Settings → More Options → Import, select evil-slip.tar.gz, and click Import. The CMS accepts and extracts the archive without error.
  5. Confirm arbitrary file write: Verify the file was written outside the extraction directory:
    curl http://<target>:3000/injected.html
    Expected response: alert('XSS') — the file is now served from the CMS domain to all visitors.
  6. Escalate to RCE (optional): For persistent RCE, craft a payload targeting a Node.js startup file (e.g., a module index.js or routes file). On the next server restart (automatic in containerized environments), the payload executes with CMS process privileges (ApostropheCMS Advisory).

Indicators of compromise

  • Network: HTTP POST requests to the CMS import endpoint (e.g., /api/v1/@apostrophecms/import-export/import) uploading .tar.gz files; unexpected HTTP GET requests to newly created files in the public/ directory (e.g., /injected.html, /evil.js) shortly after an import operation.
  • File System: Unexpected files appearing outside the CMS extraction/temp directory, particularly in public/, project root, or node_modules/; modified .env, app.config.js, package.json, or Node.js module files with recent timestamps not matching deployment history; presence of files named zip-slip-pwned.txt, evil-slip.tar.gz, or similar in temp directories.
  • Logs: CMS access logs showing import operations followed immediately by requests to previously non-existent static files; Node.js error logs showing unexpected module load behavior or startup anomalies after a restart; file system audit logs recording writes to paths outside the designated extraction directory.
  • Process: Unexpected child processes spawned by the Node.js CMS process (e.g., reverse shells, curl, wget) following a server restart after a suspicious import event (ApostropheCMS Advisory).

Mitigation and workarounds

The primary remediation is to upgrade @apostrophecms/import-export to version 3.5.3 or later, which fixes the path traversal by adding canonical-path validation before opening write streams. As interim mitigations: restrict the "Global Content Modify" permission to only fully trusted users who genuinely require import functionality; review and harden filesystem permissions so the Node.js process cannot write outside its intended directories; and implement input validation and path canonicalization for all file upload and extraction operations. No configuration-only workaround fully eliminates the risk without upgrading (ApostropheCMS Advisory, GitHub Advisory).

Community reactions

The vulnerability was discussed on Reddit's r/pwnhub community under the title "ApostropheCMS Zip Slip Vulnerability Exposes File System" and on Mastodon/Infosec.exchange by the offseq account. The Hacker Wire published a dedicated article covering the disclosure. The vulnerability was also picked up by GitLab's advisory database and multiple CVE aggregators (INCIBE, EUVD, VulDB) shortly after disclosure, indicating broad community awareness (Reddit, GitLab Advisory, The Hacker Wire).

Additional resources


Source: This report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-gvwc-5hr5-44p8HIGH7.5
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-5jh3-w3fj-6758LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-5v8x-rm7w-m4c7LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-7pqp-3q23-mwr8LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-3qg4-7mq2-gm93MEDIUMN/A
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management