{"record":{"id":"f3f71546c0db7e3e","repo":"adam-p/markdown-here","slug":"dompurify-is-required-but-not-loaded-cannot-safel","errorCode":null,"errorMessage":"DOMPurify is required but not loaded. Cannot safely parse HTML.","messagePattern":"DOMPurify is required but not loaded\\. Cannot safely parse HTML\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/common/utils.js","lineNumber":40,"sourceCode":"\n// TODO: Try to use `insertAdjacentHTML` for the inner and outer HTML functions.\n// https://developer.mozilla.org/en-US/docs/Web/API/Element.insertAdjacentHTML\n\n/**\n * Safely parse an HTML string into a DocumentFragment without executing scripts.\n * Uses DOMPurify to sanitize and parse HTML into a DocumentFragment.\n *\n * @param {string} htmlString - The HTML string to parse and sanitize.\n * @param {Document} [ownerDocument] - The document to use for creating the fragment. Defaults to the global document.\n * @param {boolean} [allowStyleTags] - Whether to allow <style> tags in the sanitized output.\n * @returns {DocumentFragment} The sanitized DocumentFragment.\n */\nfunction safelyParseHTML(htmlString, ownerDocument, allowStyleTags=false) {\n  ownerDocument = ownerDocument || document;\n\n  // DOMPurify is required for security\n  if (typeof DOMPurify === 'undefined') {\n    throw new Error('DOMPurify is required but not loaded. Cannot safely parse HTML.');\n  }\n\n  const domPurifyConfig = {\n    RETURN_DOM_FRAGMENT: true, // Return a DocumentFragment instead of a string\n    DOCUMENT: ownerDocument, // Specify which document to use for creating the fragment\n  };\n  if (allowStyleTags) {\n    domPurifyConfig.ADD_TAGS = ['style']; // Allow <style> tags\n    domPurifyConfig.FORCE_BODY = true; // Ensure <style> tags are processed correctly\n  }\n\n  // Sanitize and parse HTML into a DocumentFragment\n  const docFrag = DOMPurify.sanitize(htmlString, domPurifyConfig);\n\n  return docFrag;\n}\n\n// Assigning a string directly to `element.innerHTML` is potentially dangerous:","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/adam-p/markdown-here/blob/e00d005299922198aef968e0cd42b275525c20a6/src/common/utils.js#L22-L58","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — DOMPurify never attached to global scope\nimport DOMPurify from 'dompurify';\nsafelyParseHTML(userHtml); // throws: DOMPurify is required but not loaded\n\n// after\nimport DOMPurify from 'dompurify';\nglobalThis.DOMPurify = DOMPurify;\nsafelyParseHTML(userHtml);","handlingStrategy":"validation","validationCode":"// Assert the dependency is on the global scope before any HTML parsing.\nfunction assertDomPurifyReady() {\n  if (typeof DOMPurify === 'undefined') {\n    throw new Error('DOMPurify missing on global scope — load it before calling safelyParseHTML');\n  }\n}\n// call during module/app init, not only at the parse site","typeGuard":"function isDomPurifyAvailable() {\n  return typeof DOMPurify !== 'undefined' && typeof DOMPurify.sanitize === 'function';\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["security","xss","dompurify","html","initialization","sanitization"],"backgroundTag":null,"analyzedSha":"e00d005299922198aef968e0cd42b275525c20a6","analyzedAt":"2026-08-13T00:39:36.904Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}