Skip to content

etherpad-lite

v3.2.0 Feature

This release adds 2 notable features for engineering teams evaluating rollout.

Published 12d Productivity & Wikis
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

collaboration collaborative collaborative-ai collaborative-editing collaborative-framework collaborative-research
+9 more
collaborative-writing document documents etherpad pdf-generation rich-text-editor video-conference video-conferencing web-editor

Affected surfaces

auth rbac

ReleasePort's take

Moderate signal
editorial:auto 12d

Etherpad v3.2.0 adds first‑class reverse‑proxy support and improves admin UI visibility of runtime values.

Why it matters: The new ingress handling respects X-Forwarded-Prefix/X-Ingress-Path for deployments behind proxies, while the admin page now displays resolved env‑pill values next to placeholders, aiding configuration accuracy.

Summary

AI summary

Updates Internal / contributor-facing, Notable fixes, and Notable enhancements across a mixed release.

Changes in this release

Feature Medium

Adds first-class reverse-proxy / ingress support honoring X-Forwarded-Prefix and X-Ingress-Path under trustProxy.

Adds first-class reverse-proxy / ingress support honoring X-Forwarded-Prefix and X-Ingress-Path under trustProxy.

Source: llm_adapter@2026-05-22

Confidence: high

Feature Medium

Admin settings page now shows resolved runtime values next to env-pill placeholders.

Admin settings page now shows resolved runtime values next to env-pill placeholders.

Source: llm_adapter@2026-05-22

Confidence: high

Feature Medium

Adds admin `saveSettings` backend specs and e2e test covering persistence across restarts.

Adds admin `saveSettings` backend specs and e2e test covering persistence across restarts.

Source: llm_adapter@2026-05-22

Confidence: high

Feature Medium

Enhances bug report template to ask contributors about code‑base abstraction match, aiming to reduce premature generalisation fixes.

Enhances bug report template to ask contributors about code‑base abstraction match, aiming to reduce premature generalisation fixes.

Source: llm_adapter@2026-05-22

Confidence: low

Feature Medium

Multiple localisation updates from translatewiki.net integrated into Etherpad.

Multiple localisation updates from translatewiki.net integrated into Etherpad.

Source: llm_adapter@2026-05-22

Confidence: low

Dependency Medium

Updates multiple dependencies: ueberdb2 6.0.3 → 6.1.2, semver 7.8.0 → 7.8.1, lru-cache 11.3.6 → 11.5.0, @elastic/elasticsearch 9.4.0 → 9.4.1, pg 8.20.0 → 8.21.0, openapi-backend 5.16.1 → 5.17.0, tsx 4.22.0 → 4.22.3, @tanstack/react-query 5.100.10 → 5.100.11 plus dev tools, js-cookie 3.0.6 → 3.0.7.

Updates multiple dependencies: ueberdb2 6.0.3 → 6.1.2, semver 7.8.0 → 7.8.1, lru-cache 11.3.6 → 11.5.0, @elastic/elasticsearch 9.4.0 → 9.4.1, pg 8.20.0 → 8.21.0, openapi-backend 5.16.1 → 5.17.0, tsx 4.22.0 → 4.22.3, @tanstack/react-query 5.100.10 → 5.100.11 plus dev tools, js-cookie 3.0.6 → 3.0.7.

Source: llm_adapter@2026-05-22

Confidence: low

Bugfix Medium

Admin pads filter chip applies server-side before pagination, fixing incorrect totals and missing empty pads.

Admin pads filter chip applies server-side before pagination, fixing incorrect totals and missing empty pads.

Source: llm_adapter@2026-05-22

Confidence: high

Bugfix Medium

Outdated version gritter now resolves author from token cookie instead of missing session, making it fire in production.

Outdated version gritter now resolves author from token cookie instead of missing session, making it fire in production.

Source: llm_adapter@2026-05-22

Confidence: high

Bugfix Medium

Silences spurious "could not translate element content" warning for select elements lacking text nodes.

Silences spurious "could not translate element content" warning for select elements lacking text nodes.

Source: llm_adapter@2026-05-22

Confidence: low

Refactor Medium

CI swaps archived `ep_readonly_guest` plugin for maintained `ep_guest`, unblocking anonymizeAuthorSocket tests.

CI swaps archived `ep_readonly_guest` plugin for maintained `ep_guest`, unblocking anonymizeAuthorSocket tests.

Source: llm_adapter@2026-05-22

Confidence: high

Full changelog

3.2.0

3.2 adds first-class reverse-proxy / ingress support — X-Forwarded-Prefix and X-Ingress-Path are now honoured under trustProxy, so Etherpad can live under a subpath (Traefik, Nginx, Kubernetes Ingress) without breaking the PWA manifest, social-meta URLs, or any of the bootstrap asset links. The admin settings page learns to show resolved runtime values next to ${VAR:default} placeholders, the v3.1.0 admin pad-list filter chips now apply server-side (so "show empty pads" no longer returns 0–12 of hundreds), and the v3.1.0 redesigned outdated-version gritter actually fires in production now (the session-based author lookup it shipped with always returned null for pad visitors).

Notable enhancements

  • HTTP — accept X-Forwarded-Prefix and X-Ingress-Path under trustProxy (#7802 / #7806). With trustProxy: true, Etherpad now honours X-Forwarded-Prefix (de-facto Traefik / Spring) and X-Ingress-Path (Kubernetes Ingress) in addition to the prefix it already inferred from the request path. The shared sanitizeProxyPath helper added in 3.1.0 (defence-in-depth: [A-Za-z0-9_./-] only, //+ collapsed, .. traversal rejected) is extended to the new headers and applied consistently across /manifest.json, socialMeta og:url / og:image, and the index.html / pad.html / timeslider.html / export_html.html templates (manifest links, jslicense links, reconnect URLs). A pre-existing .. segment-count miscalculation in pad.html / timeslider.html that broke the manifest link when served from a deep subpath is also fixed in passing. New end-to-end suite covers the prefix-applied / prefix-ignored matrix under trustProxy=true|false for both header names. settings.json.template documents the new headers alongside the existing trustProxy notes.
  • Admin settings — resolved runtime values surface on env-pill chips (#7803 / #7807). The /admin/settings socket payload now carries a new resolved field alongside the existing raw-file results blob, carrying the actual in-memory settings module run through a new redactor (AdminSettingsRedact) that replaces known-sensitive paths (users.*.password, dbSettings.password, sso.clients[*].client_secret, sessionKey, …) with [REDACTED]. The admin SPA's EnvPill renders a → active value chip when the path is resolved, or → •••••• with a redacted tooltip when the server returned the sentinel — so port: ${PORT:9001} now shows → 9001 (or whatever the live value is) instead of silently falling back to the template default. Old admin SPAs that don't read resolved continue to work; the save round-trip is unchanged so ${VAR:default} literals are still preserved verbatim on disk. The admin test script glob picks up .test.tsx alongside .test.ts so the new EnvPill and resolveByPath tests run under tsx --test.

Notable fixes

  • Admin pads — filter chip now applies server-side, before pagination (#7798). The 3.1.0 admin pad-list filter chips (active / recent / empty / stale) ran on the client after the 12-row page slice had already arrived. On a deployment with hundreds of pads, clicking "empty pads" on page 1 only matched the 0–12 empties that happened to land in the current page, with the pagination footer reporting nonsense totals (reported on a 3.1.0 deployment). The filter is now part of the padLoad socket query — pattern filter on names runs first (cheap), metadata hydration for the matching pad universe is gated on a non-all filter or a non-padName sort and runs under a 16-way concurrency cap (was unbounded Promise.all, which fanned out to thousands of in-flight padManager.getPad() reads on busy deployments), then the filter chip, then sort + slice. total reflects the filtered universe so the footer makes sense. Older admin clients that don't send filter keep working — the server defaults to all. The if/else if ladder that duplicated the hydrate-and-sort loop per sortBy is folded into one pipeline with a single comparator switch.
  • Pad outdated notice — author now resolved from token cookie, not session (Qodo #7804 / #7805). The 3.1.0 redesigned outdated-version gritter never fired in production. resolveRequestAuthor() looked for an authorID on req.session.user, which Etherpad does not populate for pad visitors (express-session only carries the admin-login user), so computeOutdated() always returned EMPTY. The lookup now mirrors how the socket.io handshake resolves pad-visitor identity — read the HttpOnly token (or <prefix>token) cookie and call authorManager.getAuthorId(token, user) via a dynamic import (same circular-init guard pattern the file already uses for PadManager). The admin OpenAPI document gains a description note clarifying that /api/version-status is a public pad-side endpoint that lives in the admin doc only because it shares the same internal route registration.
  • Localisation — silence spurious "could not translate element content" warning (#7797). <select data-l10n-id="…"> with <option> element children — the pattern used by ep_headings2, ep_align, ep_font_size, ep_font_family, … — used to drop into the textContent branch of html10n.translateNode, hunt for a text-node child to overwrite, find none, and emit Unexpected error: could not translate element content for key … on every pad load. The SELECT / INPUT / TEXTAREA aria-label fallback already lived inside the same else-branch after the warning, so the accessible name landed correctly but the noisy console line still fired. Form-control elements now short-circuit into the aria-label path before the text-node hunt — aria-label is the only sensible localization target for these elements (a <select>'s text is its <option> labels, not its own name). Closes the console warning reported on Etherpad 3.1.0.

Internal / contributor-facing

  • CI — swap archived ep_readonly_guest for ep_guest in the plugin matrix (#7795 / #7808). ep_readonly_guest is archived (read-only on GitHub) and its authenticate hook unconditionally swapped req.session.user with a read-only guest, even when the request carried an HTTP Authorization header. That silently demoted admin login attempts and stalled the anonymizeAuthorSocket tests for 14 min/run on every with-plugins CI matrix. The pre-fix theory from 3.1.0 (#7796) blamed ep_hash_auth.handleMessage; that was a red herring — handleMessage only fires on the /pad namespace, never on /settings. ep_guest is the maintained successor (same authors, same purpose); 1.0.72 on npm already defers to basic auth / admin paths. Swapping the matrix unblocks the anonymizeAuthorSocket suite on Linux, Windows, and the upgrade-from-latest-release workflow. The runtime probe added in #7796 stays — it still catches any other authenticate-hook plugin that rejects the test's plain-text credentials (e.g. a future hashed-only plugin).
  • Tests — admin saveSettings round-trip + cross-restart persistence (#7819 / #7820 / #7821). The admin saveSettings socket had zero direct backend coverage and the existing e2e "restart works" test only checked that the page renders after a restart, neither of which catches a deployment that resets settings.json on restart, nor the user-visible workflow that triggered #7819 (add a top-level plugin block via Raw, save, watch it disappear). Three new backend specs (adminSettingsSave.ts) verify byte-for-byte write, top-level-block augmentation round-tripping through the next load, and /* */ comments surviving the write path. A new e2e spec mirrors the #7819 user workflow — open Raw, prepend an ep_oauth-shaped top-level block, save, restartEtherpad(), re-login, confirm the block is still in Raw and surfaces as its own Form-view section (Ep oauth from humanize()). A separate docker.yml job (adminSettings_7819.ts) authenticates via POST /admin-auth/ (always-requireAdmin, regardless of settings.requireAuthentication), saves a hand-built minimal-but-viable settings document containing a marker block, docker exec test greps for it, docker restarts the container, waits for the health probe, and re-greps. Both checks must pass.
  • Bug report template now asks contributors whether the abstraction in their proposed fix matches the rest of the codebase, to head off premature-generalisation fixes earlier in review.

Dependencies

  • ueberdb2 6.0.3 → 6.1.2 (two patch releases of cleanup on top of the 6.1.0 findKeysPaged API that the 3.1.0 sessionstorage OOM fix relies on).
  • semver 7.8.0 → 7.8.1, lru-cache 11.3.6 → 11.5.0, @elastic/elasticsearch 9.4.0 → 9.4.1, pg 8.20.0 → 8.21.0, openapi-backend 5.16.1 → 5.17.0, tsx 4.22.0 → 4.22.3, @tanstack/react-query 5.100.10 → 5.100.11 + @tanstack/react-query-devtools, js-cookie 3.0.6 → 3.0.7, plus two dev-dependency group bumps.

Localisation

  • Multiple updates from translatewiki.net.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track etherpad-lite

Get notified when new releases ship.

Sign up free

About etherpad-lite

Etherpad: A modern really-real-time collaborative document editor.

All releases →

Related context

Related tools

Earlier breaking changes

  • v3.0.0 Debian package depends on `nodejs (>= 24)`.
  • v3.0.0 `swagger-ui-express` removed; `/api-docs` serves vendored Scalar.
  • v3.0.0 `pnpm` floor raised to `[email protected]`.
  • v3.0.0 Minimum required Node.js version is now 24.

Beta — feedback welcome: [email protected]