CVE-2026-55087 Overview
CVE-2026-55087 is a reflected cross-site scripting [CWE-79] vulnerability in Etherpad, a widely deployed real-time collaborative editor. The flaw affects versions from 2.1.0 up to, but not including, 3.1.0. Etherpad substitutes the attacker-controlled x-proxy-path request header into HTML, JavaScript, and CSS responses under the /admin path without sanitization. The response also lacks Vary: x-proxy-path and Cache-Control: private, no-store directives. A shared proxy or CDN can cache the poisoned response and serve injected script to an administrator. Version 3.0.0 additionally accepts protocol-relative header values in the /p/:pad/timeslider redirect, enabling open redirection to attacker-controlled hosts.
Critical Impact
An unauthenticated attacker can poison cached admin responses to execute JavaScript in an administrator's browser session, leading to full administrative compromise of the Etherpad instance.
Affected Products
- Etherpad versions 2.1.0 through 3.0.x (all releases prior to 3.1.0)
- Etherpad 3.0.0 specifically, for the /p/:pad/timeslider open redirect variant
- Deployments where upstream infrastructure allows client-supplied x-proxy-path headers to reach the Etherpad backend
Discovery Timeline
- 2026-08-19 - CVE-2026-55087 published to the National Vulnerability Database
- 2026-08-19 - Last updated in NVD database
Technical Details for CVE-2026-55087
Vulnerability Analysis
The vulnerability is a reflected cross-site scripting flaw amplified by cache poisoning. Etherpad reads the x-proxy-path HTTP header and inlines its value into /admin responses across multiple content types. Because the header is neither sanitized nor context-encoded, an attacker can inject arbitrary HTML, JavaScript, or CSS. Downstream shared caches then store the tainted response and replay it to any administrator whose request matches the cache key. Exploitation requires that an attacker can send headers that reach the Etherpad instance and that user interaction (an admin visiting /admin) occurs. Successful exploitation yields script execution in the administrator's authenticated context, exposing session data, admin actions, and configuration control.
Root Cause
The root cause lies in src/node/hooks/express/admin.ts, which substitutes x-proxy-path into templated output without escaping and without emitting cache-safety headers. The missing Vary: x-proxy-path directive means intermediaries do not differentiate cache entries by header value. The missing Cache-Control: private, no-store allows shared caches to store admin responses. A related defect in src/node/hooks/express/specialpages.ts accepts protocol-relative values (for example, //attacker.example) when constructing the timeslider redirect, converting the header into an open redirect primitive.
Attack Vector
An attacker issues a crafted request to a cached path under /admin with a malicious x-proxy-path header containing script payloads. When the response is cached by a CDN or reverse proxy, subsequent administrator visits retrieve the poisoned copy and execute the injected script. In the timeslider variant, the attacker lures an admin to a link that triggers a redirect to an external host via the manipulated header.
// Patch excerpt from src/node/db/API.ts (Etherpad 3.0.2 hardening, PR #7784)
import AttributeMap from '../../static/js/AttributeMap';
import {deserializeOps} from '../../static/js/Changeset';
import ChatMessage from '../../static/js/ChatMessage';
import {Builder} from "../../static/js/Builder";
import {Attribute} from "../../static/js/types/Attribute";
// Mirror of `Pad.SYSTEM_AUTHOR_ID`. Inlined to avoid a circular load
// (API <-> Pad) at module init time.
const SYSTEM_AUTHOR_ID = 'a.etherpad-system';
import settings from '../utils/Settings';
Source: GitHub Commit 8c6104c
Detection Methods for CVE-2026-55087
Indicators of Compromise
- Inbound HTTP requests to /admin or /p/*/timeslider containing x-proxy-path headers with <script>, javascript:, quotes, or protocol-relative // prefixes
- Cache entries at CDN or reverse-proxy tier serving /admin responses that vary unexpectedly between users
- Unexpected 3xx redirects from /p/:pad/timeslider pointing to external hosts
- Administrator browser sessions issuing unexpected admin API calls shortly after visiting /admin
Detection Strategies
- Inspect access logs at the reverse proxy and application tier for x-proxy-path header values containing HTML metacharacters or scheme-relative URLs
- Compare Etherpad response bodies for reflected header content by replaying representative requests with distinct header values
- Audit CDN cache configuration to identify whether /admin responses are cacheable and whether cache keys account for request headers
Monitoring Recommendations
- Alert on any client-supplied x-proxy-path header reaching Etherpad from untrusted network segments
- Baseline admin panel traffic and flag anomalous JavaScript-triggered admin API activity from admin sessions
- Continuously monitor Etherpad version strings in service inventory to identify instances below 3.1.0
How to Mitigate CVE-2026-55087
Immediate Actions Required
- Upgrade Etherpad to version 3.1.0 or later, which contains the fix
- Strip or reject x-proxy-path headers at the edge proxy or load balancer if they originate from untrusted clients
- Disable shared caching of /admin responses until the upgrade is deployed
- Rotate administrator sessions and credentials if evidence of exploitation is found
Patch Information
The issue is fixed in Etherpad 3.1.0. The remediation, delivered via GitHub Pull Request #7784 and Commit 8c6104c, tightens server-side handling of the x-proxy-path header and validates redirect targets. See the GitHub Security Advisory GHSA-fjgc-3mj7-8rg8 and the Etherpad 3.1.0 release for full release notes.
Workarounds
- Configure the front-end proxy to unset or overwrite the x-proxy-path header on all inbound requests
- Restrict /admin access to trusted networks via IP allowlisting or VPN
- Force Cache-Control: private, no-store on /admin responses at the reverse proxy layer
- Reject protocol-relative values in any header the application uses for redirect construction
# Nginx example: strip x-proxy-path from client requests and prevent caching of /admin
location /admin {
proxy_set_header x-proxy-path "";
proxy_hide_header Cache-Control;
add_header Cache-Control "private, no-store" always;
proxy_pass http://etherpad_backend;
}
location ~ ^/p/.+/timeslider$ {
proxy_set_header x-proxy-path "";
proxy_pass http://etherpad_backend;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

