etherpad-lite/src/node
John McLear 01500ca70c
chore(deps): vendor the unmaintained security escaper into core (#7993)
* chore(deps): vendor the unmaintained `security` escaper into core

The `security` npm package (escapeHTML / escapeHTMLAttribute and the JS/CSS
encoders) has had no release since 2012, yet it sits directly in Etherpad's
client-side XSS-defense path (pad_utils, domline) and the server-side HTML
export. Rather than keep a 14-year-old, single-maintainer dependency guarding
output encoding, vendor its implementation into core.

- static/js/security.ts now contains the escaping logic directly (reproduced
  verbatim from security@1.0.0, MIT, Chad Weider — byte-identical output) and
  no longer does `require('security')`. The full public API is preserved, so
  plugins that `require('ep_etherpad-lite/static/js/security')` keep working
  unchanged.
- pad_utils.ts requires the local './security' module instead of the bare
  'security' specifier (domline.ts and ExportHtml.ts already did).
- Drop `security` from src/package.json dependencies and from Minify's
  LIBRARY_WHITELIST (no bare specifier is served to the browser anymore).

Added tests/backend/specs/security.ts locking the byte-for-byte escaping
output so the vendored copy can never silently drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: use ESM named exports so vitest can resolve the security module

CI "Run the new vitest tests" failed with `Cannot find module './security'`
from pad_utils.ts. vitest/vite's CJS require() shim doesn't add a `.ts`
extension when resolving a relative specifier, so `require('./security')`
couldn't locate security.ts. (The old bare `require('security')` resolved to
a real .js in node_modules, which is why this only surfaced after vendoring.)

- security.ts now uses ESM `export const` for the seven helpers instead of a
  `module.exports = {...}` block.
- pad_utils.ts imports it as `import * as Security from './security'`, which
  goes through vite's resolver (knows .ts) and is also properly typed.

CJS consumers (domline.ts, ExportHtml.ts, the backend spec) keep working via
tsx/esbuild ESM->CJS interop. Verified: tsc clean, full vitest suite 721
passing, and the mocha security/export/import specs 27 passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: force fresh run (prior run used a stale merge ref after reopen)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: remove ReDoS in vendored JSON-string-literal regex

CodeQL flagged a high-severity exponential-backtracking alert on the
JSON-string-literal regex vendored from the `security` package:
`/"(?:\\.|[^"])*"/`. The `[^"]` class also matches a backslash, so it overlaps
with the `\\.` alternative and backtracks exponentially on adversarial input
like `"\!\!\!...` (no closing quote). The original lived inside node_modules so
it was never scanned; vendoring it surfaced the alert.

Fix to the canonical linear form `/"(?:[^"\\]|\\.)*"/`, where the backslash is
excluded from the character class so the two alternatives are mutually
exclusive. It matches exactly the same well-formed JSON string literals (and
encodeJavaScriptData only ever runs it over JSON.stringify output), so behaviour
is unchanged for valid input.

Added tests: encodeJavaScriptData output + a ReDoS guard that runs the regex
over 50k adversarial chars and asserts it returns in well under a second.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:56:40 +01:00
..
db PadManager: reject unreachable '.' and '..' pad ids (#7962) 2026-06-16 11:13:02 +01:00
eejs chore: migrated settings to esm6 (#7062) 2025-08-04 22:42:50 +02:00
handler fix(pad): keep token-less Delete pad reachable without pad-wide settings (#7959) (#7960) 2026-06-17 15:18:23 +01:00
hooks PadManager: reject unreachable '.' and '..' pad ids (#7962) 2026-06-16 11:13:02 +01:00
security Hardening: API request handling, random IDs, and plugin loading (#7906) 2026-06-07 19:17:39 +02:00
types fix(admin/pads): apply filter chip server-side, before pagination (#7798) 2026-05-17 19:43:36 +01:00
updater Fix offline/air-gapped Docker boot: stop pnpm self-provisioning the pinned version (#7911) (#7918) 2026-06-09 09:31:00 +01:00
utils chore(deps): vendor the unmaintained security escaper into core (#7993) 2026-06-22 09:56:40 +01:00
metrics.ts chore: added prometheus support in Etherpad 2025-08-25 20:34:29 +02:00
padaccess.ts feat: make cookie names configurable with prefix setting (#7450) 2026-04-05 01:58:29 +01:00
prom-instruments.ts feat(metrics): 3 Prometheus counters for scaling dive (#7756) (#7762) 2026-05-15 19:54:42 +01:00
prometheus.ts feat(metrics): 3 Prometheus counters for scaling dive (#7756) (#7762) 2026-05-15 19:54:42 +01:00
README.md Added typescript to etherpad 2024-02-05 21:13:02 +01:00
server.ts fix: eliminate the Windows backend silent-ELIFECYCLE flake (handler gate + Node 24.16.0) (#7866) 2026-05-28 16:12:34 +01:00
stats.ts Added typescript to etherpad 2024-02-05 21:13:02 +01:00

About the folder structure

  • db - all modules that are accessing the data structure and are communicating directly to the database
  • handler - all modules that respond directly to requests/messages of the browser
  • utils - helper modules

Module name conventions

Module file names start with a capital letter and uses camelCase

Where does it start?

server.ts is started directly