Skip to main content

ep_etherpad-lite EUVDEUVD-2026-62741

| CVE-2026-55086 MEDIUM
Improper Link Resolution Before File Access (CWE-59)
2026-08-13 https://github.com/ether/etherpad GHSA-2jwf-f4xq-f24h
4.2
CVSS 3.1 · Vendor: https://github.com/ether/etherpad
Share

Severity by source

Vendor (https://github.com/ether/etherpad) PRIMARY
4.2 MEDIUM
AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N
vuln.today AI
4.2 MEDIUM

Local access and PRNG state reconstruction required (AV:L/AC:H/PR:L); scope change to Etherpad-process-owner files confirmed by symlink mechanics; no availability impact.

3.1 AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N
4.0 AV:L/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N

Primary rating from Vendor (https://github.com/ether/etherpad).

CVSS VectorVendor: https://github.com/ether/etherpad

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

Lifecycle Timeline

2
Source Code Evidence Fetched
Aug 13, 2026 - 15:24 vuln.today
Analysis Generated
Aug 13, 2026 - 15:24 vuln.today

DescriptionCVE.org

Description

src/node/handler/ImportHandler.ts and src/node/handler/ExportHandler.ts both compute their temporary working-file paths as:

ts
const randNum = Math.floor(Math.random() * 0xFFFFFFFF);
const srcFile = `${os.tmpdir()}/etherpad_export_${randNum}.html`;
const destFile = `${os.tmpdir()}/etherpad_export_${randNum}.${type}`;

Two flaws compound:

  1. Math.random() is not crypto-secure. It yields at most ~32 bits of entropy and is predictable across calls within the same Node process (V8 shares PRNG state between consecutive Math.random() invocations). An attacker on the same host who observes any earlier temp-file name from logs or other side channels can predict subsequent names.
  2. The paths land in os.tmpdir(). On a typical Linux system this is /tmp - a shared world-writable directory. An unprivileged local attacker can pre-create a symbolic link at a predicted path pointing at any file the Etherpad process can write:
   ln -s /etc/etherpad/SESSIONKEY.txt /tmp/etherpad_export_<predicted>.html

When ExportHandler calls fs.writeFile(srcFile, html) (or ImportHandler calls fs.rename(srcFile, destFile) / soffice writes its converted output to the path), the open syscall follows the symlink and either reads from or overwrites the linked target. For deployments where the Etherpad process runs as a privileged user (notably some Docker base images that run as root, snap confinement edge cases, or hand-rolled systemd units), this becomes arbitrary file overwrite.

The Import path is more impactful in practice: the file content the attacker can land in the symlink target is partially attacker-controlled (the post-soffice/post-mammoth conversion output of the uploaded document).

Severity rationale

  • AV:L - requires local access to the host that runs Etherpad. Multi-tenant hosts (shared dev boxes, k8s shared-node setups, single-server CI workers) are the realistic threat surface.
  • AC:H - attacker needs to predict the temp filename, which requires observing prior names or shared PRNG state.
  • PR:L - any unprivileged local account.
  • UI:N - no user interaction.
  • S:C - scope change from local user to whatever the Etherpad process can write.
  • C:L / I:L / A:N - bounded by what the Etherpad process can already touch; confidentiality is via secondary read-paths (the LibreOffice conversion error log can echo bytes from the symlinked file).

Single-tenant deployments where only the Etherpad operator has shell access on the host are not exposed.

Affected versions

  • All ep_etherpad-lite versions through v3.0.0 (inclusive). The Math.floor(Math.random() * 0xFFFFFFFF) pattern is present in src/node/handler/ImportHandler.ts and src/node/handler/ExportHandler.ts for as far back as the repository history extends - older than the 2024-03-16 snapshot at commit 107598b where it first appears in the current file paths, and predating the v1.x era.

Patched versions

  • ep_etherpad-lite >= 3.1.0 - the fix is on develop HEAD as commit 8c6104c. Update this field with the actual tagged release version when it ships.

Proof of concept (sketch)

# Pre-condition: attacker has shell on the same host as Etherpad,
# has read access to /tmp, and Etherpad's process can write to the
# chosen target (e.g. runs as root inside a Docker container).
# 1. Observe a temp filename from logs (or guess via prior exports).
TARGET=/etc/etherpad/SESSIONKEY.txt
GUESS=/tmp/etherpad_export_$(./predict-next-random)$EXT
# implementation-specific
# 2. Place the symlink before Etherpad creates the file.
ln -s "$TARGET" "$GUESS"
# 3. Trigger an export from the Etherpad UI (or via the API).
# Etherpad calls fs.writeFile(srcFile, ...) which open()s the symlink
# target with O_WRONLY|O_TRUNC and clobbers $TARGET with HTML content.

In practice the exact reproduction depends on the host's PRNG state predictability and the deployment's process-owner privileges. A reliable exploit chain needs setpriv-style host access or a sibling tenant.

Workarounds

  • Run Etherpad in a container with a private /tmp (Docker: --tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m, systemd: PrivateTmp=true).
  • Ensure the Etherpad process does NOT run as root and has write access only to its own data directory.
  • Set TMPDIR to an Etherpad-private directory in the environment.

Fix

Patched in 8c6104c (PR #7784):

diff
-const randNum = Math.floor(Math.random() * 0xFFFFFFFF);
+const randNum = crypto.randomBytes(16).toString('hex');

128 bits of CSPRNG entropy. Predicting the next filename is no longer feasible.

A bigger follow-up - per-request mkdtemp subdirectories with O_EXCL/O_NOFOLLOW semantics - is deferred to a later release; the immediate window (predictable 32-bit collisions across processes) is what the patch closes.

Resources

  • Patched in: https://github.com/ether/etherpad/pull/7784 (squash commit 8c6104c).
  • Math.random() is not appropriate for security-sensitive contexts. See the MDN guidance for Math.random() and the Node.js recommendation to use crypto.randomBytes for unpredictable values.

Credits

Reported during an internal security audit by Claude (via @JohnMcLear).

AnalysisAI

Predictable temporary file paths in Etherpad's import and export handlers expose multi-tenant deployments to a symlink-based file overwrite attack. All ep_etherpad-lite versions through v3.0.0 are affected; exploitation requires local host access, an unprivileged OS account, and - for high-impact scenarios - the Etherpad process running as root, a common default in many Docker base images. A proof-of-concept sketch is included in the vendor advisory GHSA-2jwf-f4xq-f24h; no public weaponized exploit code beyond that sketch exists and this vulnerability is not listed in the CISA KEV catalog.

Technical ContextAI

The affected package is pkg:npm/ep_etherpad-lite. The vulnerable code appears in src/node/handler/ImportHandler.ts and src/node/handler/ExportHandler.ts, both of which generate temporary file paths using Math.floor(Math.random() * 0xFFFFFFFF) - a non-cryptographic V8 PRNG with at most approximately 32 bits of effective entropy whose internal state is shared across all Math.random() calls within the same Node.js process. Because these paths land in os.tmpdir() (typically /tmp on Linux, a shared world-writable directory), a local attacker who predicts the next filename can pre-create a symbolic link there before Etherpad's fs.writeFile or fs.rename call executes. Node.js file I/O follows the symlink at open() time without O_NOFOLLOW protection, redirecting the write to the attacker's target. CWE-59 (Improper Link Resolution Before File Access) captures this root cause precisely. The fix committed at 8c6104c replaces the insecure call with crypto.randomBytes(16).toString('hex'), yielding 128 bits of CSPRNG entropy and rendering filename prediction computationally infeasible.

RemediationAI

Upgrade ep_etherpad-lite to version 3.1.0 or later, which replaces the insecure temp file naming with crypto.randomBytes(16).toString('hex') as patched in commit 8c6104c via PR #7784 (https://github.com/ether/etherpad/pull/7784). For deployments unable to upgrade immediately, three compensating controls are available. First, configure a private /tmp mount for the Etherpad process - Docker deployments should add --tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m to the container run command; systemd units should set PrivateTmp=true - this prevents other local OS accounts from observing or pre-placing symlinks in Etherpad's temp space, though it does not address the PRNG weakness itself. Second, ensure the Etherpad process does NOT run as root; limiting the process to a dedicated low-privilege service account dramatically reduces the blast radius of any successful symlink attack to only files owned or writable by that account. Third, set the TMPDIR environment variable to an Etherpad-private directory with mode 0700 and restricted ownership. Controls two and three in combination provide strong mitigation for most deployment scenarios. Note that the upstream patch closes only the immediate filename-prediction window; a more complete hardening using per-request mkdtemp subdirectories with O_EXCL/O_NOFOLLOW semantics is explicitly deferred by the vendor to a future release.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2026-66384 MEDIUM POC
5.3 Aug 12

Path traversal in JFrog Artifactory (CWE-22) enables an authenticated low-privilege user to write data outside the inten

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-52806 CRITICAL POC
9.9 Jun 23

Remote code execution in Gogs through 0.14.2 allows authenticated users (and unauthenticated attackers on default-config

CVE-2026-56274 HIGH POC
8.7 Jun 23

Remote code execution in Flowise before 3.1.2 allows any authenticated user (or API caller with chatflow view/update per

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

CVE-2025-34221 CRITICAL POC
10.0 Sep 29

Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2

Share

EUVD-2026-62741 vulnerability details – vuln.today

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