CVE-2026-55086: ep_etherpad-lite Import/export Uses Math.random() For Temp Vulnerability
MODERATECVE-2026-55086 is a MODERATE (CVSS 4.2) import/export uses math.random() for temp vulnerability (CWE-377: Insecure Temporary File) affecting ep_etherpad-lite libraries in the npm ecosystem. The issue involves import/export uses math.random() for temp file paths; predictable paths on shared /tmp enable symlink-based file overwrite. Remediation is available by upgrading affected packages to version 3.1.0.
CVE-2026-55086 at a Glance
Security Impact
CVSS: 4.2
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N).
How to Fix CVE-2026-55086
To remediate this vulnerability, upgrade all affected ep_etherpad-lite dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install ep_etherpad-lite@3.1.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls ep_etherpad-lite
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-55086, inspect your project dependencies using npm:
npm ls ep_etherpad-lite
Analyze the terminal output to locate any version of ep_etherpad-lite in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.1.0), your application is affected.
Note: The npm ls ep_etherpad-lite command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-377: Insecure Temporary File, where creating and using insecure temporary files can leave application and system data vulnerable to attack. In ep_etherpad-lite, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-55086 Affected ep_etherpad-lite Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
ep_etherpad-lite
|
npm |
< 3.1.0
|
3.1.0
|
References
Frequently Asked Questions
What is CVE-2026-55086?
Which ep_etherpad-lite versions are affected?
What version fixes CVE-2026-55086?
Is ep_etherpad-lite affected?
What is the CVSS score of CVE-2026-55086?
What CWE is associated with CVE-2026-55086?
How can I check npm dependencies for CVE-2026-55086?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-2jwf-f4xq-f24h",
"modified" : "2026-08-13T14:11:08Z",
"published" : "2026-08-13T14:11:07Z",
"aliases" : [ "CVE-2026-55086" ],
"summary" : "ep_etherpad-lite: Import/export uses Math.random() for temp file paths; predictable paths on shared /tmp enable symlink-based file overwrite",
"details" : "## Description\n\n`src/node/handler/ImportHandler.ts` and `src/node/handler/ExportHandler.ts` both compute their temporary working-file paths as:\n\n```ts\nconst randNum = Math.floor(Math.random() * 0xFFFFFFFF);\nconst srcFile = `${os.tmpdir()}/etherpad_export_${randNum}.html`;\nconst destFile = `${os.tmpdir()}/etherpad_export_${randNum}.${type}`;\n```\n\nTwo flaws compound:\n\n1. **`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.\n\n2. **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:\n\n ```\n ln -s /etc/etherpad/SESSIONKEY.txt /tmp/etherpad_export_<predicted>.html\n ```\n\n 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.\n\nThe 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).\n\n## Severity rationale\n\n- **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.\n- **AC:H** — attacker needs to predict the temp filename, which requires observing prior names or shared PRNG state.\n- **PR:L** — any unprivileged local account.\n- **UI:N** — no user interaction.\n- **S:C** — scope change from local user to whatever the Etherpad process can write.\n- **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).\n\nSingle-tenant deployments where only the Etherpad operator has shell access on the host are not exposed.\n\n## Affected versions\n\n- 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`](https://github.com/ether/etherpad/commit/107598b) where it first appears in the current file paths, and predating the v1.x era.\n\n## Patched versions\n\n- `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.\n\n## Proof of concept (sketch)\n\n```\n# Pre-condition: attacker has shell on the same host as Etherpad,\n# has read access to /tmp, and Etherpad's process can write to the\n# chosen target (e.g. runs as root inside a Docker container).\n\n# 1. Observe a temp filename from logs (or guess via prior exports).\nTARGET=/etc/etherpad/SESSIONKEY.txt\nGUESS=/tmp/etherpad_export_$(./predict-next-random)$EXT # implementation-specific\n\n# 2. Place the symlink before Etherpad creates the file.\nln -s \"$TARGET\" \"$GUESS\"\n\n# 3. Trigger an export from the Etherpad UI (or via the API).\n# Etherpad calls fs.writeFile(srcFile, ...) which open()s the symlink\n# target with O_WRONLY|O_TRUNC and clobbers $TARGET with HTML content.\n```\n\nIn 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.\n\n## Workarounds\n\n- Run Etherpad in a container with a private `/tmp` (Docker: `--tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m`, systemd: `PrivateTmp=true`).\n- Ensure the Etherpad process does NOT run as root and has write access only to its own data directory.\n- Set `TMPDIR` to an Etherpad-private directory in the environment.\n\n## Fix\n\nPatched in [`8c6104c`](https://github.com/ether/etherpad/commit/8c6104c) (PR [#7784](https://github.com/ether/etherpad/pull/7784)):\n\n```diff\n-const randNum = Math.floor(Math.random() * 0xFFFFFFFF);\n+const randNum = crypto.randomBytes(16).toString('hex');\n```\n\n128 bits of CSPRNG entropy. Predicting the next filename is no longer feasible.\n\nA 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.\n\n## Resources\n\n- Patched in: https://github.com/ether/etherpad/pull/7784 (squash commit `8c6104c`).\n- `Math.random()` is not appropriate for security-sensitive contexts. See the MDN guidance for [`Math.random()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) and the Node.js recommendation to use [`crypto.randomBytes`](https://nodejs.org/api/crypto.html#cryptorandombytessize-callback) for unpredictable values.\n\n## Credits\n\nReported during an internal security audit by Claude (via @JohnMcLear).",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "ep_etherpad-lite"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.1.0"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.0.0"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/ether/etherpad/security/advisories/GHSA-2jwf-f4xq-f24h"
}, {
"type" : "WEB",
"url" : "https://github.com/ether/etherpad/pull/7784"
}, {
"type" : "WEB",
"url" : "https://github.com/ether/etherpad/commit/8c6104c5d5daf41f0d454acc04d42dffa0e0d996"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/ether/etherpad"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-377", "CWE-59" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-08-13T14:11:07Z",
"nvd_published_at" : null
}
}