Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1import type { Config, UseProfilesConfig } from './config';2import type { DOMPurify, HooksMap, HookFunction, WindowLike } from './types';3import * as TAGS from './tags.js';4import * as ATTRS from './attrs.js';5import * as EXPRESSIONS from './regexp.js';6import {7 addToSet,8 clone,9 entries,10 freeze,11 seal,12 arrayForEach,13 arrayIsArray,14 arrayLastIndexOf,15 arrayPop,16 arrayPush,17 arraySplice,18 stringMatch,19 stringReplace,20 stringToLowerCase,21 stringToString,22 stringIndexOf,23 stringTrim,24 regExpTest,25 isRegex,26 typeErrorCreate,27 lookupGetter,28 create,29 objectHasOwnProperty,30 stringifyValue,31} from './utils.js';32 33export type { Config } from './config';34 35export type {36 DOMPurify,37 RemovedElement,38 RemovedAttribute,39 HookName,40 NodeHook,41 ElementHook,42 DocumentFragmentHook,43 UponSanitizeElementHook,44 UponSanitizeAttributeHook,45 UponSanitizeElementHookEvent,46 UponSanitizeAttributeHookEvent,47 WindowLike,48} from './types';49 50declare const VERSION: string;51 52// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType53const NODE_TYPE = {54 element: 1,55 attribute: 2,56 text: 3,57 cdataSection: 4,58 entityReference: 5, // Deprecated59 entityNode: 6, // Deprecated60 processingInstruction: 7,61 comment: 8,62 document: 9,63 documentType: 10,64 documentFragment: 11,65 notation: 12, // Deprecated66};67 68const getGlobal = function (): WindowLike {69 return typeof window === 'undefined' ? null : window;70};71 72/**73 * Creates a no-op policy for internal use only.74 * Don't export this function outside this module!75 * @param trustedTypes The policy factory.76 * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).77 * @return The policy created (or null, if Trusted Types78 * are not supported or creating the policy failed).79 */80const _createTrustedTypesPolicy = function (81 trustedTypes: TrustedTypePolicyFactory,82 purifyHostElement: HTMLScriptElement83) {84 if (85 typeof trustedTypes !== 'object' ||86 typeof trustedTypes.createPolicy !== 'function'87 ) {88 return null;89 }90 91 // Allow the callers to control the unique policy name92 // by adding a data-tt-policy-suffix to the script element with the DOMPurify.93 // Policy creation with duplicate names throws in Trusted Types.94 let suffix = null;95 const ATTR_NAME = 'data-tt-policy-suffix';96 if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {97 suffix = purifyHostElement.getAttribute(ATTR_NAME);98 }99 100 const policyName = 'dompurify' + (suffix ? '#' + suffix : '');101 102 try {103 return trustedTypes.createPolicy(policyName, {104 createHTML(html) {105 return html;106 },107 createScriptURL(scriptUrl) {108 return scriptUrl;109 },110 });111 } catch (_) {112 // Policy creation failed (most likely another DOMPurify script has113 // already run). Skip creating the policy, as this will only cause errors114 // if TT are enforced.115 console.warn(116 'TrustedTypes policy ' + policyName + ' could not be created.'117 );118 return null;119 }120};121 122const _createHooksMap = function (): HooksMap {123 return {124 afterSanitizeAttributes: [],125 afterSanitizeElements: [],126 afterSanitizeShadowDOM: [],127 beforeSanitizeAttributes: [],128 beforeSanitizeElements: [],129 beforeSanitizeShadowDOM: [],130 uponSanitizeAttribute: [],131 uponSanitizeElement: [],132 uponSanitizeShadowNode: [],133 };134};135 136/**137 * Resolve a set-valued configuration option: a fresh set built from138 * cfg[key] when it is an own array property (seeded with a clone of139 * options.base when given, case-normalized via options.transform),140 * the fallback set otherwise.141 *142 * @param cfg the cloned, prototype-free configuration object143 * @param key the configuration property to read144 * @param fallback the set to use when the option is absent or not an array145 * @param options transform and optional base set to merge into146 * @returns the resolved set147 */148const _resolveSetOption = function (149 cfg: Config,150 key: keyof Config,151 fallback: Record<string, boolean>,152 options: {153 transform: Parameters<typeof addToSet>[2];154 base?: Record<string, boolean>;155 }156): Record<string, boolean> {157 return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key])158 ? addToSet(159 options.base ? clone(options.base) : {},160 cfg[key] as readonly unknown[],161 options.transform162 )163 : fallback;164};165 166function createDOMPurify(window: WindowLike = getGlobal()): DOMPurify {167 const DOMPurify: DOMPurify = (root: WindowLike) => createDOMPurify(root);168 169 DOMPurify.version = VERSION;170 171 DOMPurify.removed = [];172 173 if (174 !window ||175 !window.document ||176 window.document.nodeType !== NODE_TYPE.document ||177 !window.Element178 ) {179 // Not running in a browser, provide a factory function180 // so that you can pass your own Window181 DOMPurify.isSupported = false;182 183 return DOMPurify;184 }185 186 let { document } = window;187 188 const originalDocument = document;189 const currentScript: HTMLScriptElement =190 originalDocument.currentScript as HTMLScriptElement;191 const {192 DocumentFragment,193 HTMLTemplateElement,194 Node,195 Element,196 NodeFilter,197 NamedNodeMap = window.NamedNodeMap || (window as any).MozNamedAttrMap,198 HTMLFormElement,199 DOMParser,200 trustedTypes,201 } = window;202 203 const ElementPrototype = Element.prototype;204 205 const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');206 const remove = lookupGetter(ElementPrototype, 'remove');207 const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');208 const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');209 const getParentNode = lookupGetter(ElementPrototype, 'parentNode');210 const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');211 const getAttributes = lookupGetter(ElementPrototype, 'attributes');212 const getNodeType =213 Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;214 const getNodeName =215 Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;216 const getOwnerDocument =217 Node && Node.prototype218 ? lookupGetter(Node.prototype, 'ownerDocument')219 : null;220 221 // As per issue #47, the web-components registry is inherited by a222 // new document created via createHTMLDocument. As per the spec223 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)224 // a new empty registry is used when creating a template contents owner225 // document, so we use that as our parent document to ensure nothing226 // is inherited.227 if (typeof HTMLTemplateElement === 'function') {228 const template = document.createElement('template');229 if (template.content && template.content.ownerDocument) {230 document = template.content.ownerDocument;231 }232 }233 234 let trustedTypesPolicy;235 let emptyHTML = '';236 237 // The instance's own internal Trusted Types policy. Unlike a caller-supplied238 // `TRUSTED_TYPES_POLICY`, this is created at most once — Trusted Types throws239 // on duplicate policy names — and is the only policy allowed to persist240 // across configurations and survive `clearConfig()`.241 let defaultTrustedTypesPolicy;242 let defaultTrustedTypesPolicyResolved = false;243 244 // Tracks whether we are already inside a call to the configured Trusted Types245 // policy (`createHTML` or `createScriptURL`). If a supplied policy callback246 // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would247 // re-enter the policy and recurse until the stack overflows. We detect that248 // re-entry and throw a clear, actionable error instead. The guard is shared249 // across both callbacks, because either one re-entering `sanitize` triggers250 // the same unbounded recursion.251 let IN_TRUSTED_TYPES_POLICY = 0;252 const _assertNotInTrustedTypesPolicy = function (): void {253 if (IN_TRUSTED_TYPES_POLICY > 0) {254 throw typeErrorCreate(255 'A configured TRUSTED_TYPES_POLICY callback (createHTML or ' +256 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' +257 'infinite recursion. Do not pass a policy whose callbacks wrap ' +258 'DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted ' +259 'Types" section of the README.'260 );261 }262 };263 264 const _createTrustedHTML = function (html: string): string {265 _assertNotInTrustedTypesPolicy();266 267 IN_TRUSTED_TYPES_POLICY++;268 try {269 return trustedTypesPolicy.createHTML(html);270 } finally {271 IN_TRUSTED_TYPES_POLICY--;272 }273 };274 275 const _createTrustedScriptURL = function (scriptUrl: string): string {276 _assertNotInTrustedTypesPolicy();277 278 IN_TRUSTED_TYPES_POLICY++;279 try {280 return trustedTypesPolicy.createScriptURL(scriptUrl);281 } finally {282 IN_TRUSTED_TYPES_POLICY--;283 }284 };285 286 // Lazily resolve (and cache) the instance's internal default policy.287 // Resolution is attempted at most once: a successful `createPolicy` cannot be288 // repeated (Trusted Types throws on duplicate names), and a failed or289 // unsupported attempt must not be retried on every parse.290 const _getDefaultTrustedTypesPolicy = function () {291 if (!defaultTrustedTypesPolicyResolved) {292 defaultTrustedTypesPolicy = _createTrustedTypesPolicy(293 trustedTypes,294 currentScript295 );296 defaultTrustedTypesPolicyResolved = true;297 }298 299 return defaultTrustedTypesPolicy;300 };301 302 const {303 implementation,304 createNodeIterator,305 createDocumentFragment,306 getElementsByTagName,307 } = document;308 const { importNode } = originalDocument;309 310 let hooks = _createHooksMap();311 312 /**313 * Expose whether this browser supports running the full DOMPurify.314 */315 DOMPurify.isSupported =316 typeof entries === 'function' &&317 typeof getParentNode === 'function' &&318 implementation &&319 implementation.createHTMLDocument !== undefined;320 321 const {322 MUSTACHE_EXPR,323 ERB_EXPR,324 TMPLIT_EXPR,325 DATA_ATTR,326 ARIA_ATTR,327 IS_SCRIPT_OR_DATA,328 ATTR_WHITESPACE,329 CUSTOM_ELEMENT,330 } = EXPRESSIONS;331 332 let { IS_ALLOWED_URI } = EXPRESSIONS;333 334 /**335 * We consider the elements and attributes below to be safe. Ideally336 * don't add any new ones but feel free to remove unwanted ones.337 */338 339 /* allowed element names */340 let ALLOWED_TAGS = null;341 const DEFAULT_ALLOWED_TAGS = addToSet({}, [342 ...TAGS.html,343 ...TAGS.svg,344 ...TAGS.svgFilters,345 ...TAGS.mathMl,346 ...TAGS.text,347 ]);348 349 /* Allowed attribute names */350 let ALLOWED_ATTR = null;351 const DEFAULT_ALLOWED_ATTR = addToSet({}, [352 ...ATTRS.html,353 ...ATTRS.svg,354 ...ATTRS.mathMl,355 ...ATTRS.xml,356 ]);357 358 /*359 * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.360 * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)361 * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)362 * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.363 */364 let CUSTOM_ELEMENT_HANDLING = Object.seal(365 create(null, {366 tagNameCheck: {367 writable: true,368 configurable: false,369 enumerable: true,370 value: null,371 },372 attributeNameCheck: {373 writable: true,374 configurable: false,375 enumerable: true,376 value: null,377 },378 allowCustomizedBuiltInElements: {379 writable: true,380 configurable: false,381 enumerable: true,382 value: false,383 },384 })385 );386 387 /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */388 let FORBID_TAGS = null;389 390 /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */391 let FORBID_ATTR = null;392 393 /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */394 const EXTRA_ELEMENT_HANDLING = Object.seal(395 create(null, {396 tagCheck: {397 writable: true,398 configurable: false,399 enumerable: true,400 value: null,401 },402 attributeCheck: {403 writable: true,404 configurable: false,405 enumerable: true,406 value: null,407 },408 })409 );410 411 /* Decide if ARIA attributes are okay */412 let ALLOW_ARIA_ATTR = true;413 414 /* Decide if custom data attributes are okay */415 let ALLOW_DATA_ATTR = true;416 417 /* Decide if unknown protocols are okay */418 let ALLOW_UNKNOWN_PROTOCOLS = false;419 420 /* Decide if self-closing tags in attributes are allowed.421 * Usually removed due to a mXSS issue in jQuery 3.0 */422 let ALLOW_SELF_CLOSE_IN_ATTR = true;423 424 /* Output should be safe for common template engines.425 * This means, DOMPurify removes data attributes, mustaches and ERB426 */427 let SAFE_FOR_TEMPLATES = false;428 429 /* Output should be safe even for XML used within HTML and alike.430 * This means, DOMPurify removes comments when containing risky content.431 */432 let SAFE_FOR_XML = true;433 434 /* Decide if document with <html>... should be returned */435 let WHOLE_DOCUMENT = false;436 437 /* Track whether config is already set on this instance of DOMPurify. */438 let SET_CONFIG = false;439 440 /* Pristine allowlist bindings captured at setConfig() time. On the441 * persistent-config path sanitize() restores the sets from these before442 * the per-walk hook clone-guard, so a hook's in-call widening cannot443 * carry across calls. Null until setConfig() is called; reset by444 * clearConfig(). */445 let SET_CONFIG_ALLOWED_TAGS = null;446 let SET_CONFIG_ALLOWED_ATTR = null;447 448 /* Decide if all elements (e.g. style, script) must be children of449 * document.body. By default, browsers might move them to document.head */450 let FORCE_BODY = false;451 452 /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html453 * string (or a TrustedHTML object if Trusted Types are supported).454 * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead455 */456 let RETURN_DOM = false;457 458 /* Decide if a DOM `DocumentFragment` should be returned, instead of a html459 * string (or a TrustedHTML object if Trusted Types are supported) */460 let RETURN_DOM_FRAGMENT = false;461 462 /* Try to return a Trusted Type object instead of a string, return a string in463 * case Trusted Types are not supported */464 let RETURN_TRUSTED_TYPE = false;465 466 /* Output should be free from DOM clobbering attacks?467 * This sanitizes markups named with colliding, clobberable built-in DOM APIs.468 */469 let SANITIZE_DOM = true;470 471 /* Achieve full DOM Clobbering protection by isolating the namespace of named472 * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.473 *474 * HTML/DOM spec rules that enable DOM Clobbering:475 * - Named Access on Window (§7.3.3)476 * - DOM Tree Accessors (§3.1.5)477 * - Form Element Parent-Child Relations (§4.10.3)478 * - Iframe srcdoc / Nested WindowProxies (§4.8.5)479 * - HTMLCollection (§4.2.10.2)480 *481 * Namespace isolation is implemented by prefixing `id` and `name` attributes482 * with a constant string, i.e., `user-content-`483 */484 let SANITIZE_NAMED_PROPS = false;485 const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';486 487 /* Keep element content when removing element? */488 let KEEP_CONTENT = true;489 490 /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead491 * of importing it into a new Document and returning a sanitized copy */492 let IN_PLACE = false;493 494 /* Allow usage of profiles like html, svg and mathMl */495 let USE_PROFILES: UseProfilesConfig | false = {};496 497 /* Tags to ignore content of when KEEP_CONTENT is true */498 let FORBID_CONTENTS = null;499 const DEFAULT_FORBID_CONTENTS = addToSet({}, [500 'annotation-xml',501 'audio',502 'colgroup',503 'desc',504 'foreignobject',505 'head',506 'iframe',507 'math',508 'mi',509 'mn',510 'mo',511 'ms',512 'mtext',513 'noembed',514 'noframes',515 'noscript',516 'plaintext',517 'script',518 // <selectedcontent> mirrors the selected <option>'s subtree, cloned by519 // the UA (customizable <select>) — including any on* handlers — and the520 // engine re-mirrors synchronously whenever a removal changes which521 // option/selectedcontent is current, even inside DOMPurify's inert522 // DOMParser document. Hoisting its children on removal re-inserts a fresh523 // mirror target ahead of the walk, which the engine refills, looping524 // forever (DoS) and amplifying output. Dropping its content on removal525 // (rather than hoisting) breaks that cascade; the content is a duplicate526 // of the option, which is sanitized on its own. See campaign-3 F1/F6.527 'selectedcontent',528 'style',529 'svg',530 'template',531 'thead',532 'title',533 'video',534 'xmp',535 ]);536 537 /* Tags that are safe for data: URIs */538 let DATA_URI_TAGS = null;539 const DEFAULT_DATA_URI_TAGS = addToSet({}, [540 'audio',541 'video',542 'img',543 'source',544 'image',545 'track',546 ]);547 548 /* Attributes safe for values like "javascript:" */549 let URI_SAFE_ATTRIBUTES = null;550 const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [551 'alt',552 'class',553 'for',554 'id',555 'label',556 'name',557 'pattern',558 'placeholder',559 'role',560 'summary',561 'title',562 'value',563 'style',564 'xmlns',565 ]);566 567 const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';568 const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';569 const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';570 /* Document namespace */571 let NAMESPACE = HTML_NAMESPACE;572 let IS_EMPTY_INPUT = false;573 574 /* Allowed XHTML+XML namespaces */575 let ALLOWED_NAMESPACES = null;576 const DEFAULT_ALLOWED_NAMESPACES = addToSet(577 {},578 [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE],579 stringToString580 );581 582 const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze([583 'mi',584 'mo',585 'mn',586 'ms',587 'mtext',588 ]);589 let MATHML_TEXT_INTEGRATION_POINTS = addToSet(590 {},591 DEFAULT_MATHML_TEXT_INTEGRATION_POINTS592 );593 594 const DEFAULT_HTML_INTEGRATION_POINTS = freeze(['annotation-xml']);595 let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);596 597 // Certain elements are allowed in both SVG and HTML598 // namespace. We need to specify them explicitly599 // so that they don't get erroneously deleted from600 // HTML namespace.601 const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [602 'title',603 'style',604 'font',605 'a',606 'script',607 ]);608 609 /* Parsing of strict XHTML documents */610 let PARSER_MEDIA_TYPE: null | DOMParserSupportedType = null;611 const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];612 const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';613 let transformCaseFunc: null | Parameters<typeof addToSet>[2] = null;614 615 /* Keep a reference to config to pass to hooks */616 let CONFIG: Config | null = null;617 618 /* Ideally, do not touch anything below this line */619 /* ______________________________________________ */620 621 const formElement = document.createElement('form');622 623 const isRegexOrFunction = function (624 testValue: unknown625 ): testValue is Function | RegExp {626 return testValue instanceof RegExp || testValue instanceof Function;627 };628 629 /**630 * _parseConfig631 *632 * @param cfg optional config literal633 */634 // eslint-disable-next-line complexity635 const _parseConfig = function (cfg: Config = {}): void {636 if (CONFIG && CONFIG === cfg) {637 return;638 }639 640 /* Shield configuration object from tampering */641 if (!cfg || typeof cfg !== 'object') {642 cfg = {};643 }644 645 /* Shield configuration object from prototype pollution */646 cfg = clone(cfg);647 648 PARSER_MEDIA_TYPE =649 // eslint-disable-next-line unicorn/prefer-includes650 SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1651 ? DEFAULT_PARSER_MEDIA_TYPE652 : cfg.PARSER_MEDIA_TYPE;653 654 // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.655 transformCaseFunc =656 PARSER_MEDIA_TYPE === 'application/xhtml+xml'657 ? stringToString658 : stringToLowerCase;659 660 /* Set configuration parameters */661 ALLOWED_TAGS = _resolveSetOption(662 cfg,663 'ALLOWED_TAGS',664 DEFAULT_ALLOWED_TAGS,665 { transform: transformCaseFunc }666 );667 ALLOWED_ATTR = _resolveSetOption(668 cfg,669 'ALLOWED_ATTR',670 DEFAULT_ALLOWED_ATTR,671 { transform: transformCaseFunc }672 );673 ALLOWED_NAMESPACES = _resolveSetOption(674 cfg,675 'ALLOWED_NAMESPACES',676 DEFAULT_ALLOWED_NAMESPACES,677 { transform: stringToString }678 );679 URI_SAFE_ATTRIBUTES = _resolveSetOption(680 cfg,681 'ADD_URI_SAFE_ATTR',682 DEFAULT_URI_SAFE_ATTRIBUTES,683 { transform: transformCaseFunc, base: DEFAULT_URI_SAFE_ATTRIBUTES }684 );685 DATA_URI_TAGS = _resolveSetOption(686 cfg,687 'ADD_DATA_URI_TAGS',688 DEFAULT_DATA_URI_TAGS,689 { transform: transformCaseFunc, base: DEFAULT_DATA_URI_TAGS }690 );691 FORBID_CONTENTS = _resolveSetOption(692 cfg,693 'FORBID_CONTENTS',694 DEFAULT_FORBID_CONTENTS,695 { transform: transformCaseFunc }696 );697 FORBID_TAGS = _resolveSetOption(cfg, 'FORBID_TAGS', clone({}), {698 transform: transformCaseFunc,699 });700 FORBID_ATTR = _resolveSetOption(cfg, 'FORBID_ATTR', clone({}), {701 transform: transformCaseFunc,702 });703 USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES')704 ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object'705 ? clone(cfg.USE_PROFILES)706 : cfg.USE_PROFILES707 : false;708 709 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true710 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true711 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false712 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true713 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false714 SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true715 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false716 RETURN_DOM = cfg.RETURN_DOM || false; // Default false717 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false718 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false719 FORCE_BODY = cfg.FORCE_BODY || false; // Default false720 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true721 SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false722 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true723 IN_PLACE = cfg.IN_PLACE || false; // Default false724 IS_ALLOWED_URI = isRegex(cfg.ALLOWED_URI_REGEXP)725 ? cfg.ALLOWED_URI_REGEXP726 : EXPRESSIONS.IS_ALLOWED_URI; // Default regexp727 728 NAMESPACE =729 typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace730 731 MATHML_TEXT_INTEGRATION_POINTS =732 objectHasOwnProperty(cfg, 'MATHML_TEXT_INTEGRATION_POINTS') &&733 cfg.MATHML_TEXT_INTEGRATION_POINTS &&734 typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === 'object'735 ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS)736 : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); // Default built-in map737 738 HTML_INTEGRATION_POINTS =739 objectHasOwnProperty(cfg, 'HTML_INTEGRATION_POINTS') &&740 cfg.HTML_INTEGRATION_POINTS &&741 typeof cfg.HTML_INTEGRATION_POINTS === 'object'742 ? clone(cfg.HTML_INTEGRATION_POINTS)743 : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); // Default built-in map744 745 const customElementHandling =746 objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') &&747 cfg.CUSTOM_ELEMENT_HANDLING &&748 typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object'749 ? clone(cfg.CUSTOM_ELEMENT_HANDLING)750 : create(null);751 752 CUSTOM_ELEMENT_HANDLING = create(null);753 754 if (755 objectHasOwnProperty(customElementHandling, 'tagNameCheck') &&756 isRegexOrFunction(customElementHandling.tagNameCheck)757 ) {758 CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined759 }760 761 if (762 objectHasOwnProperty(customElementHandling, 'attributeNameCheck') &&763 isRegexOrFunction(customElementHandling.attributeNameCheck)764 ) {765 CUSTOM_ELEMENT_HANDLING.attributeNameCheck =766 customElementHandling.attributeNameCheck; // Default undefined767 }768 769 if (770 objectHasOwnProperty(771 customElementHandling,772 'allowCustomizedBuiltInElements'773 ) &&774 typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean'775 ) {776 CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =777 customElementHandling.allowCustomizedBuiltInElements; // Default undefined778 }779 780 seal(CUSTOM_ELEMENT_HANDLING);781 782 if (SAFE_FOR_TEMPLATES) {783 ALLOW_DATA_ATTR = false;784 }785 786 if (RETURN_DOM_FRAGMENT) {787 RETURN_DOM = true;788 }789 790 /* Parse profile info */791 if (USE_PROFILES) {792 ALLOWED_TAGS = addToSet({}, TAGS.text);793 ALLOWED_ATTR = create(null);794 if (USE_PROFILES.html === true) {795 addToSet(ALLOWED_TAGS, TAGS.html);796 addToSet(ALLOWED_ATTR, ATTRS.html);797 }798 799 if (USE_PROFILES.svg === true) {800 addToSet(ALLOWED_TAGS, TAGS.svg);801 addToSet(ALLOWED_ATTR, ATTRS.svg);802 addToSet(ALLOWED_ATTR, ATTRS.xml);803 }804 805 if (USE_PROFILES.svgFilters === true) {806 addToSet(ALLOWED_TAGS, TAGS.svgFilters);807 addToSet(ALLOWED_ATTR, ATTRS.svg);808 addToSet(ALLOWED_ATTR, ATTRS.xml);809 }810 811 if (USE_PROFILES.mathMl === true) {812 addToSet(ALLOWED_TAGS, TAGS.mathMl);813 addToSet(ALLOWED_ATTR, ATTRS.mathMl);814 addToSet(ALLOWED_ATTR, ATTRS.xml);815 }816 }817 818 /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent819 * leaking across calls when switching from function to array config */820 EXTRA_ELEMENT_HANDLING.tagCheck = null;821 EXTRA_ELEMENT_HANDLING.attributeCheck = null;822 823 /* Merge configuration parameters */824 if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {825 if (typeof cfg.ADD_TAGS === 'function') {826 EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;827 } else if (arrayIsArray(cfg.ADD_TAGS)) {828 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {829 ALLOWED_TAGS = clone(ALLOWED_TAGS);830 }831 832 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);833 }834 }835 836 if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {837 if (typeof cfg.ADD_ATTR === 'function') {838 EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;839 } else if (arrayIsArray(cfg.ADD_ATTR)) {840 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {841 ALLOWED_ATTR = clone(ALLOWED_ATTR);842 }843 844 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);845 }846 }847 848 if (849 objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') &&850 arrayIsArray(cfg.ADD_URI_SAFE_ATTR)851 ) {852 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);853 }854 855 if (856 objectHasOwnProperty(cfg, 'FORBID_CONTENTS') &&857 arrayIsArray(cfg.FORBID_CONTENTS)858 ) {859 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {860 FORBID_CONTENTS = clone(FORBID_CONTENTS);861 }862 863 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);864 }865 866 if (867 objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') &&868 arrayIsArray(cfg.ADD_FORBID_CONTENTS)869 ) {870 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {871 FORBID_CONTENTS = clone(FORBID_CONTENTS);872 }873 874 addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);875 }876 877 /* Add #text in case KEEP_CONTENT is set to true */878 if (KEEP_CONTENT) {879 ALLOWED_TAGS['#text'] = true;880 }881 882 /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */883 if (WHOLE_DOCUMENT) {884 addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);885 }886 887 /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */888 if (ALLOWED_TAGS.table) {889 addToSet(ALLOWED_TAGS, ['tbody']);890 delete FORBID_TAGS.tbody;891 }892 893 // Re-derive the active Trusted Types policy from this configuration on894 // every parse. The active policy must never be sticky closure state that895 // outlives the config that set it: a caller-supplied policy left in place896 // after `clearConfig()` — or after a later call that supplied none, or897 // `TRUSTED_TYPES_POLICY: null` — could sign a subsequent "default"898 // `RETURN_TRUSTED_TYPE` result with a foreign, possibly unsafe policy.899 // See GHSA-vxr8-fq34-vvx9.900 if (cfg.TRUSTED_TYPES_POLICY) {901 if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {902 throw typeErrorCreate(903 'TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.'904 );905 }906 907 if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {908 throw typeErrorCreate(909 'TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.'910 );911 }912 913 // A caller-supplied policy applies to this configuration only.914 const previousTrustedTypesPolicy = trustedTypesPolicy;915 trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;916 917 // Sign local variables required by `sanitize`. If the supplied policy's918 // `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this919 // throws via the re-entrancy guard. Restore the previous policy first so920 // the instance is not left in a poisoned state. See #1422.921 try {922 emptyHTML = _createTrustedHTML('');923 } catch (error) {924 trustedTypesPolicy = previousTrustedTypesPolicy;925 throw error;926 }927 } else if (cfg.TRUSTED_TYPES_POLICY === null) {928 // Explicit opt-out for this call: perform no Trusted Types signing and929 // create nothing (so a strict `trusted-types` CSP that disallows a930 // `dompurify` policy can still call `sanitize` from inside its own931 // policy — see #1422). Resetting to `undefined` rather than a sticky932 // `null` also drops any previously retained caller policy, so it cannot933 // resurface on a later call, while still allowing the next config-less934 // call to restore the internal default policy. See GHSA-vxr8-fq34-vvx9.935 trustedTypesPolicy = undefined;936 emptyHTML = '';937 } else {938 // No policy supplied: keep the currently active policy if one is set — a939 // previously supplied policy is intentionally sticky across config-less940 // calls — otherwise fall back to the instance's own internal policy,941 // created at most once. (A policy supplied for a *single* call still942 // lingers by design; what must not linger is a policy whose configuration943 // has been torn down via `clearConfig()`, which restores the default.)944 if (trustedTypesPolicy === undefined) {945 trustedTypesPolicy = _getDefaultTrustedTypesPolicy();946 }947 948 // Sign internal variables only when a policy is active. A falsy policy949 // (Trusted Types unsupported, creation failed, or an explicit opt-out)950 // leaves `emptyHTML` as a plain string, so we never call `.createHTML` on951 // a non-policy and throw. See #1422.952 if (trustedTypesPolicy && typeof emptyHTML === 'string') {953 emptyHTML = _createTrustedHTML('');954 }955 }956 957 // Prevent further manipulation of configuration.958 // Not available in IE8, Safari 5, etc.959 if (freeze) {960 freeze(cfg);961 }962 963 CONFIG = cfg;964 };965 966 /* Keep track of all possible SVG and MathML tags967 * so that we can perform the namespace checks968 * correctly. */969 const ALL_SVG_TAGS = addToSet({}, [970 ...TAGS.svg,971 ...TAGS.svgFilters,972 ...TAGS.svgDisallowed,973 ]);974 const ALL_MATHML_TAGS = addToSet({}, [975 ...TAGS.mathMl,976 ...TAGS.mathMlDisallowed,977 ]);978 979 /**980 * Namespace rules for an element in the SVG namespace.981 *982 * @param tagName the element's lowercase tag name983 * @param parent the (possibly simulated) parent node984 * @param parentTagName the parent's lowercase tag name985 * @returns true if a spec-compliant parser could produce this element986 */987 const _checkSvgNamespace = function (988 tagName: string,989 parent: { namespaceURI?: string },990 parentTagName: string991 ): boolean {992 // The only way to switch from HTML namespace to SVG993 // is via <svg>. If it happens via any other tag, then994 // it should be killed.995 if (parent.namespaceURI === HTML_NAMESPACE) {996 return tagName === 'svg';997 }998 999 // The only way to switch from MathML to SVG is via <svg>1000 // if the parent is either <annotation-xml> or a MathML1001 // text integration point.1002 if (parent.namespaceURI === MATHML_NAMESPACE) {1003 return (1004 tagName === 'svg' &&1005 (parentTagName === 'annotation-xml' ||1006 MATHML_TEXT_INTEGRATION_POINTS[parentTagName])1007 );1008 }1009 1010 // We only allow elements that are defined in SVG1011 // spec. All others are disallowed in SVG namespace.1012 return Boolean(ALL_SVG_TAGS[tagName]);1013 };1014 1015 /**1016 * Namespace rules for an element in the MathML namespace.1017 *1018 * @param tagName the element's lowercase tag name1019 * @param parent the (possibly simulated) parent node1020 * @param parentTagName the parent's lowercase tag name1021 * @returns true if a spec-compliant parser could produce this element1022 */1023 const _checkMathMlNamespace = function (1024 tagName: string,1025 parent: { namespaceURI?: string },1026 parentTagName: string1027 ): boolean {1028 // The only way to switch from HTML namespace to MathML1029 // is via <math>. If it happens via any other tag, then1030 // it should be killed.1031 if (parent.namespaceURI === HTML_NAMESPACE) {1032 return tagName === 'math';1033 }1034 1035 // The only way to switch from SVG to MathML is via1036 // <math> and HTML integration points1037 if (parent.namespaceURI === SVG_NAMESPACE) {1038 return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];1039 }1040 1041 // We only allow elements that are defined in MathML1042 // spec. All others are disallowed in MathML namespace.1043 return Boolean(ALL_MATHML_TAGS[tagName]);1044 };1045 1046 /**1047 * Namespace rules for an element in the HTML namespace.1048 *1049 * @param tagName the element's lowercase tag name1050 * @param parent the (possibly simulated) parent node1051 * @param parentTagName the parent's lowercase tag name1052 * @returns true if a spec-compliant parser could produce this element1053 */1054 const _checkHtmlNamespace = function (1055 tagName: string,1056 parent: { namespaceURI?: string },1057 parentTagName: string1058 ): boolean {1059 // The only way to switch from SVG to HTML is via1060 // HTML integration points, and from MathML to HTML1061 // is via MathML text integration points1062 if (1063 parent.namespaceURI === SVG_NAMESPACE &&1064 !HTML_INTEGRATION_POINTS[parentTagName]1065 ) {1066 return false;1067 }1068 1069 if (1070 parent.namespaceURI === MATHML_NAMESPACE &&1071 !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]1072 ) {1073 return false;1074 }1075 1076 // We disallow tags that are specific for MathML1077 // or SVG and should never appear in HTML namespace1078 return (1079 !ALL_MATHML_TAGS[tagName] &&1080 (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName])1081 );1082 };1083 1084 /**1085 * @param element a DOM element whose namespace is being checked1086 * @returns Return false if the element has a1087 * namespace that a spec-compliant parser would never1088 * return. Return true otherwise.1089 */1090 const _checkValidNamespace = function (element: Element): boolean {1091 let parent = getParentNode(element);1092 1093 // In JSDOM, if we're inside shadow DOM, then parentNode1094 // can be null. We just simulate parent in this case.1095 if (!parent || !parent.tagName) {1096 parent = {1097 namespaceURI: NAMESPACE,1098 tagName: 'template',1099 };1100 }1101 1102 const tagName = stringToLowerCase(element.tagName);1103 const parentTagName = stringToLowerCase(parent.tagName);1104 1105 if (!ALLOWED_NAMESPACES[element.namespaceURI]) {1106 return false;1107 }1108 1109 if (element.namespaceURI === SVG_NAMESPACE) {1110 return _checkSvgNamespace(tagName, parent, parentTagName);1111 }1112 1113 if (element.namespaceURI === MATHML_NAMESPACE) {1114 return _checkMathMlNamespace(tagName, parent, parentTagName);1115 }1116 1117 if (element.namespaceURI === HTML_NAMESPACE) {1118 return _checkHtmlNamespace(tagName, parent, parentTagName);1119 }1120 1121 // For XHTML and XML documents that support custom namespaces1122 if (1123 PARSER_MEDIA_TYPE === 'application/xhtml+xml' &&1124 ALLOWED_NAMESPACES[element.namespaceURI]1125 ) {1126 return true;1127 }1128 1129 // The code should never reach this place (this means1130 // that the element somehow got namespace that is not1131 // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).1132 // Return false just in case.1133 return false;1134 };1135 1136 /**1137 * _forceRemove1138 *1139 * @param node a DOM node1140 */1141 const _forceRemove = function (node: Node): void {1142 arrayPush(DOMPurify.removed, { element: node });1143 1144 try {1145 // eslint-disable-next-line unicorn/prefer-dom-node-remove1146 getParentNode(node).removeChild(node);1147 } catch (_) {1148 /* The normal detach failed — this is reached for a parentless node1149 (getParentNode() is null, so .removeChild throws). Element.prototype1150 .remove() is itself a spec no-op on a parentless node, so a recorded1151 "removal" would otherwise hand the caller back an intact,1152 payload-bearing node (e.g. a detached IN_PLACE root the mXSS canary or1153 the style-with-element-child rule decided to kill). Fail closed by1154 throwing — exactly as a clobbered root does at the IN_PLACE entry —1155 rather than trying to "neutralize" the node via its own methods.1156 Neutralizing would mean calling getAttributeNames()/removeAttribute()1157 on the node, both of which a <form> root can clobber via a named child1158 (and _isClobbered does not even probe getAttributeNames), so the1159 neutralize step could itself be silently defeated, leaving the payload1160 intact. A throw touches only the cached, clobber-safe remove() and1161 getParentNode(). Generalizes GHSA-r47g-fvhr-h676 (clobbered-form root)1162 to every root-kill reason. REPORT-3.1163 1164 This lives inside the catch, so it never fires for a normally-removed1165 in-tree node: those have a parent, removeChild() succeeds, and the1166 catch is not entered. Only a kept (parentless) root reaches here. */1167 remove(node);1168 1169 if (!getParentNode(node)) {1170 throw typeErrorCreate(1171 'a node selected for removal could not be detached from its tree ' +1172 'and cannot be safely returned; refusing to sanitize in place'1173 );1174 }1175 }1176 };1177 1178 /**1179 * _neutralizeRoot1180 *1181 * Fail-closed teardown of an in-place root after the sanitize walk aborts1182 * (campaign-3 F2). An internal throw mid-walk — e.g. a page-registered1183 * custom element's reaction detaches a node so `_forceRemove`'s deliberate1184 * parentless guard throws, or any other re-entrant engine mutation — would1185 * otherwise leave the caller's *live* tree half-sanitized, with everything1186 * after the abort point still carrying its handlers. There is no safe way1187 * to resume the walk (the tree mutated under us), so we strip the root bare:1188 * remove every child and every attribute, then let the caller's catch see1189 * the original error. Clobber-safe (cached `remove`/`childNodes`/`attributes`1190 * getters; the root was already clobber-pre-flighted at the IN_PLACE entry).1191 *1192 * @param root the in-place root to empty1193 */1194 const _neutralizeRoot = function (root: Node): void {1195 /* Strip every disallowed attribute (on* handlers included) off the whole1196 subtree BEFORE detaching anything. Detaching first would hand back1197 handler-bearing originals (e.g. an already-loading `<img onerror>`)1198 whose queued resource event still fires in page scope after we throw.1199 Clobber-safe reads; a doomed clobbered node's own attributes are1200 irrelevant while its non-clobbered descendants are reached and scrubbed. */