CVE-2026-55086: Medium severity npm/ep_etherpad-lite vulnerability

Published Aug 13, 2026
·
Updated

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()}/etherpadexport${randNum}.html; const destFile = ${os.tmpdir()}/etherpadexport${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/etherpadexport<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 epetherpad-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

- epetherpad-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/etherpadexport$(./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 OWRONLY|OTRUNC 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 OEXCL/ONOFOLLOW 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).

Affected Software

1 affected componentFixes available
npm/ep_etherpad-lite<=3.0.0
3.1.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/ep_etherpad-lite to a version that resolves this vulnerability.

    Fixed in 3.1.0
  2. Upgrade

    Upgrade ep_etherpad-lite to a version that resolves this vulnerability.

    Patch 8c6104c
  3. Configuration

    Run Etherpad in a container with a private /tmp using Docker: `--tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m`.

    Docker container /tmp mount = --tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m
  4. Configuration

    Configure the systemd unit running Etherpad with `PrivateTmp=true` so it uses a private /tmp.

    systemd unit PrivateTmp = true
  5. Configuration

    Set `TMPDIR` in the environment to an Etherpad-private directory (not the shared `/tmp`), so the symlink can’t be pre-created at a guessable path.

    Etherpad environment TMPDIR = an Etherpad-private directory
  6. Configuration

    Use a CSPRNG for temp filename generation (replace `Math.floor(Math.random() * 0xFFFFFFFF)` / `Math.random()` with `crypto.randomBytes(16).toString('hex')`).

    Node.js handler random filename generation randNum generation = crypto.randomBytes(16).toString('hex')
  7. Compensating control

    Ensure the Etherpad process does NOT run as root and has write access only to its own data directory, limiting the impact of any symlink-based overwrite.

Event History

Aug 13, 2026
Advisory Published
via GitHub·02:11 PM
Data Sourced
via GitHub·02:11 PM
DescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-55086?

The severity of CVE-2026-55086 is classified as medium with a score of 4.2.

2

How do I fix CVE-2026-55086?

To fix CVE-2026-55086, update to the latest version of npm/ep_etherpad-lite that addresses the vulnerability.

3

What impact does CVE-2026-55086 have on my system?

CVE-2026-55086 may allow local users to manipulate temporary file paths, potentially leading to information leakage.

4

Who is affected by CVE-2026-55086?

CVE-2026-55086 affects users of the npm/ep_etherpad-lite software.

5

When was CVE-2026-55086 published?

CVE-2026-55086 was published on August 13, 2026.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203