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
- 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.
- 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.
- 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).
- 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
Background
isomorphic-dompurifydepends onjsdom, which is a heavy dependency that pulls inundici(the source of 12 recent security vulnerabilities fixed in #803). We already havelinkedomas a dependency for other server-side DOM needs (e.g. Readability).Proposal
Investigate whether we can use
linkedominstead ofjsdomfor server-side DOMPurify, potentially replacingisomorphic-dompurifywith directdompurifyusage:linkedomto provide awindowobject instead ofjsdomThis would let us drop
jsdomas 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
DOMPurify.sanitize()withADD_TAGS,ADD_ATTR,FORBID_TAGS,FORBID_ATTRoptions, plusDOMPurify.addHook("afterSanitizeAttributes", ...). All of these need to work.isomorphic-dompurifyhandles the client/server split automatically. We'd need to handle this ourselves (e.g. conditional import or a thin wrapper).jsdomdirectly (beyond vitest test environment).Benefits
jsdomas a production dependency (~heavy, pulls in undici, canvas, etc.)linkedomis already in our dependency tree— Claude