Skip to content

Investigate replacing jsdom with linkedom for server-side DOMPurify #804

@brendanlong

Description

@brendanlong

Background

isomorphic-dompurify depends on jsdom, which is a heavy dependency that pulls in undici (the source of 12 recent security vulnerabilities fixed in #803). We already have linkedom as a dependency for other server-side DOM needs (e.g. Readability).

Proposal

Investigate whether we can use linkedom instead of jsdom for server-side DOMPurify, potentially replacing isomorphic-dompurify with direct dompurify usage:

  • On the client: DOMPurify uses the native browser DOM (no extra deps needed)
  • On the server: DOMPurify could use linkedom to provide a window object instead of jsdom

This would let us drop jsdom as a direct dependency entirely (it would remain as a dev dependency for vitest's test environment), reducing bundle size and the transitive dependency surface area.

Things to investigate

  1. Compatibility: Does DOMPurify work correctly with linkedom's DOM implementation? linkedom is less spec-complete than jsdom — DOMPurify may rely on DOM features that linkedom doesn't implement.
  2. Current usage: We use DOMPurify.sanitize() with ADD_TAGS, ADD_ATTR, FORBID_TAGS, FORBID_ATTR options, plus DOMPurify.addHook("afterSanitizeAttributes", ...). All of these need to work.
  3. Server-side rendering: isomorphic-dompurify handles the client/server split automatically. We'd need to handle this ourselves (e.g. conditional import or a thin wrapper).
  4. Other jsdom usages: Check if anything else depends on jsdom directly (beyond vitest test environment).

Benefits

  • Remove jsdom as a production dependency (~heavy, pulls in undici, canvas, etc.)
  • Reduce transitive dependency surface area (fewer security alerts)
  • linkedom is already in our dependency tree

— Claude

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions