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
- Ensure DOMPurify is loaded as a global before any safelyParseHTML call (include its <script> ahead of this code).
- If using a bundler/modules, assign the global explicitly: window.DOMPurify = require('dompurify'); (or import DOMPurify from 'dompurify'; globalThis.DOMPurify = DOMPurify;).
- Check your CSP allows DOMPurify to load (script-src / integrity attributes).
- 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
- Load DOMPurify as a plain <script> before your app bundle, or explicitly assign globalThis.DOMPurify in module setups.
- In Node/test environments, attach dompurify to globalThis with a jsdom window before importing code that parses HTML.
- Verify your CSP 'script-src' permits DOMPurify and that bundlers are not tree-shaking it off the global.
- Run an init-time self-check (isDomPurifyAvailable()) so the failure is loud at startup, not at first user HTML parse.
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.