adam-p/markdown-here · critical · Error

DOMPurify is required but not loaded. Cannot safely parse HT

Error message

DOMPurify is required but not loaded. Cannot safely parse HTML.

What it means

safelyParseHTML(htmlString, ownerDocument, allowStyleTags) builds a DOMPurify config and sanitizes HTML into a DocumentFragment. As a deliberate security hard-fail, it checks typeof DOMPurify === 'undefined' before doing anything and throws rather than parsing unsanitized HTML. DOMPurify must be present on the global scope before the first call; it is never imported by this module.

Source

Thrown at src/common/utils.js:40

// TODO: Try to use `insertAdjacentHTML` for the inner and outer HTML functions.
// https://developer.mozilla.org/en-US/docs/Web/API/Element.insertAdjacentHTML

/**
 * Safely parse an HTML string into a DocumentFragment without executing scripts.
 * Uses DOMPurify to sanitize and parse HTML into a DocumentFragment.
 *
 * @param {string} htmlString - The HTML string to parse and sanitize.
 * @param {Document} [ownerDocument] - The document to use for creating the fragment. Defaults to the global document.
 * @param {boolean} [allowStyleTags] - Whether to allow <style> tags in the sanitized output.
 * @returns {DocumentFragment} The sanitized DocumentFragment.
 */
function safelyParseHTML(htmlString, ownerDocument, allowStyleTags=false) {
  ownerDocument = ownerDocument || document;

  // DOMPurify is required for security
  if (typeof DOMPurify === 'undefined') {
    throw new Error('DOMPurify is required but not loaded. Cannot safely parse HTML.');
  }

  const domPurifyConfig = {
    RETURN_DOM_FRAGMENT: true, // Return a DocumentFragment instead of a string
    DOCUMENT: ownerDocument, // Specify which document to use for creating the fragment
  };
  if (allowStyleTags) {
    domPurifyConfig.ADD_TAGS = ['style']; // Allow <style> tags
    domPurifyConfig.FORCE_BODY = true; // Ensure <style> tags are processed correctly
  }

  // Sanitize and parse HTML into a DocumentFragment
  const docFrag = DOMPurify.sanitize(htmlString, domPurifyConfig);

  return docFrag;
}

// Assigning a string directly to `element.innerHTML` is potentially dangerous:

View on GitHub (pinned to e00d005299)

Solutions

  1. Ensure DOMPurify is loaded as a global before any safelyParseHTML call (include its <script> ahead of this code).
  2. If using a bundler/modules, assign the global explicitly: window.DOMPurify = require('dompurify'); (or import DOMPurify from 'dompurify'; globalThis.DOMPurify = DOMPurify;).
  3. Check your CSP allows DOMPurify to load (script-src / integrity attributes).
  4. In Node/test environments, install dompurify with a jsdom window and attach it to globalThis before running tests that hit this path.

Example fix

// before — DOMPurify never attached to global scope
import DOMPurify from 'dompurify';
safelyParseHTML(userHtml); // throws: DOMPurify is required but not loaded

// after
import DOMPurify from 'dompurify';
globalThis.DOMPurify = DOMPurify;
safelyParseHTML(userHtml);
Defensive patterns

Strategy: validation

Validate before calling

// Assert the dependency is on the global scope before any HTML parsing.
function assertDomPurifyReady() {
  if (typeof DOMPurify === 'undefined') {
    throw new Error('DOMPurify missing on global scope — load it before calling safelyParseHTML');
  }
}
// call during module/app init, not only at the parse site

Type guard

function isDomPurifyAvailable() {
  return typeof DOMPurify !== 'undefined' && typeof DOMPurify.sanitize === 'function';
}

Prevention

When it happens

Trigger: Calling safelyParseHTML before the DOMPurify <script> has executed (script load order). Running in a context where DOMPurify is module-scoped (e.g. require('dompurify')) but never assigned to window/globalThis. A Content Security Policy that blocks the DOMPurify script. A test harness or service-worker context that has no DOMPurify loaded.

Common situations: Forgetting the DOMPurify <script> include in the page; bundler tree-shaking or wrapping DOMPurify so it is no longer a global; CSP 'script-src' missing the DOMPurify origin; running the code in Node/a worker without jsdom + dompurify polyfill; upgrading DOMPurify to an ESM-only version that no longer auto-registers globally.

Related errors


AI-assisted analysis of adam-p/markdown-here@e00d005299 (2026-08-13). Data as JSON: /api/errors/f3f71546c0db7e3e. Report an issue: GitHub.