Skip to content

happy-dom is unsound as a DOMPurify test harness (NodeIterator lacks live-mutation adjustment) #202

Description

Summary

While fixing #194 (PR #201) we found that happy-dom cannot be trusted to test DOMPurify-based sanitization — it can make a broken sanitizer appear to work.

Details

DOMPurify sanitizes by walking the DOM with document.createNodeIterator(...) and removing disallowed nodes in place, mid-walk. The DOM spec requires a NodeIterator to adjust its position when the current node is removed (live-mutation adjustment). happy-dom's NodeIterator does not implement this — once DOMPurify removes the first disallowed node, iteration silently stops, and every node after it is left unsanitized.

Reproduced (both @happy-dom/[email protected] and 20.11.0):

This is a test-environment soundness problem — production runs in a real browser with a spec-compliant NodeIterator, so the shipped sanitizer is fine. But any test that validates DOMPurify behavior under happy-dom may be giving false security assurances.

Impact / action

  • PR fix: KaTeX LaTeX leak (#194), image recognition (#192), ARM64 silent exit (#190), + 1000 Genomes skill docs (#191) #201 switched the new frontend/ui sanitizer test to jsdom (added jsdom/global-jsdom/@types/jsdom devDeps).
  • frontend/workspace uses @happy-dom/global-registrator (frontend/workspace/happydom.ts). Audit whether it hosts any DOMPurify-based (or other mid-walk-mutation) tests and, if so, move them to jsdom or otherwise make them sound. Single-node XSS payloads pass even under the broken engine, so a passing test is not evidence of soundness — use a multi-node payload as a canary.

Ref: PR #201, issue #194.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions