release: v4.8.9 security hardening patch
CodeQL Analysis / Analyze CodeQL (push) Has been cancelled
Deploy Application / deploy (push) Has been cancelled
Mirror to Codeberg / mirror (push) Has been cancelled
Mirror to PrivacyGuides / mirror (push) Has been cancelled

- upgrade DOMPurify to patched release (fixes high-severity XSS GHSA-87xg-pxx2-7hvx)
- upgrade esbuild build dependency; npm audit now reports 0 vulnerabilities
- stop tracking config/ice-servers.js (TURN credentials); add example template
- production logger no longer prints error context or info/debug output
- bump version to 4.8.9 across header, manifest, README, init message
- update SECURITY.md supported-release table to v4.8.x
This commit is contained in:
lockbitchat
2026-06-15 15:08:03 -04:00
parent d11f250257
commit 366f080128
21 changed files with 691 additions and 347 deletions
+491 -177
View File
@@ -5,7 +5,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
try {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
} catch (e) {
throw mod = 0, e;
}
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
@@ -954,7 +958,7 @@ function isRegex(value) {
return false;
}
}
var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "selectedcontent", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]);
var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]);
var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]);
@@ -981,13 +985,26 @@ var ATTR_WHITESPACE = seal(
);
var DOCTYPE_NAME = seal(/^html$/i);
var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
var ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g);
var COMMENT_MARKUP_PROBE = seal(/<[/\w]/g);
var FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i);
var SELF_CLOSING_TAG = seal(/\/>/i);
var NODE_TYPE = {
element: 1,
attribute: 2,
text: 3,
cdataSection: 4,
entityReference: 5,
// Deprecated
progressingInstruction: 7,
entityNode: 6,
// Deprecated
processingInstruction: 7,
comment: 8,
document: 9
document: 9,
documentType: 10,
documentFragment: 11,
notation: 12
// Deprecated
};
var getGlobal = function getGlobal2() {
return typeof window === "undefined" ? null : window;
@@ -1029,10 +1046,13 @@ var _createHooksMap = function _createHooksMap2() {
uponSanitizeShadowNode: []
};
};
var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) {
return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
};
function createDOMPurify() {
let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
const DOMPurify = (root) => createDOMPurify(root);
DOMPurify.version = "3.4.4";
DOMPurify.version = "3.4.10";
DOMPurify.removed = [];
if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
DOMPurify.isSupported = false;
@@ -1041,14 +1061,21 @@ function createDOMPurify() {
let document2 = window2.document;
const originalDocument = document2;
const currentScript = originalDocument.currentScript;
const DocumentFragment = window2.DocumentFragment, HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window2.HTMLFormElement, DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
window2.DocumentFragment;
const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
_window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
window2.HTMLFormElement;
const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
const ElementPrototype = Element.prototype;
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
const remove = lookupGetter(ElementPrototype, "remove");
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
const getParentNode = lookupGetter(ElementPrototype, "parentNode");
const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot");
const getAttributes = lookupGetter(ElementPrototype, "attributes");
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
if (typeof HTMLTemplateElement === "function") {
const template = document2.createElement("template");
if (template.content && template.content.ownerDocument) {
@@ -1057,6 +1084,39 @@ function createDOMPurify() {
}
let trustedTypesPolicy;
let emptyHTML = "";
let defaultTrustedTypesPolicy;
let defaultTrustedTypesPolicyResolved = false;
let IN_TRUSTED_TYPES_POLICY = 0;
const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() {
if (IN_TRUSTED_TYPES_POLICY > 0) {
throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.');
}
};
const _createTrustedHTML = function _createTrustedHTML2(html2) {
_assertNotInTrustedTypesPolicy();
IN_TRUSTED_TYPES_POLICY++;
try {
return trustedTypesPolicy.createHTML(html2);
} finally {
IN_TRUSTED_TYPES_POLICY--;
}
};
const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) {
_assertNotInTrustedTypesPolicy();
IN_TRUSTED_TYPES_POLICY++;
try {
return trustedTypesPolicy.createScriptURL(scriptUrl);
} finally {
IN_TRUSTED_TYPES_POLICY--;
}
};
const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() {
if (!defaultTrustedTypesPolicyResolved) {
defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
defaultTrustedTypesPolicyResolved = true;
}
return defaultTrustedTypesPolicy;
};
const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
const importNode = originalDocument.importNode;
let hooks = _createHooksMap();
@@ -1122,7 +1182,43 @@ function createDOMPurify() {
let IN_PLACE = false;
let USE_PROFILES = {};
let FORBID_CONTENTS = null;
const DEFAULT_FORBID_CONTENTS = addToSet({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]);
const DEFAULT_FORBID_CONTENTS = addToSet({}, [
"annotation-xml",
"audio",
"colgroup",
"desc",
"foreignobject",
"head",
"iframe",
"math",
"mi",
"mn",
"mo",
"ms",
"mtext",
"noembed",
"noframes",
"noscript",
"plaintext",
"script",
// <selectedcontent> mirrors the selected <option>'s subtree, cloned by
// the UA (customizable <select>) — including any on* handlers — and the
// engine re-mirrors synchronously whenever a removal changes which
// option/selectedcontent is current, even inside DOMPurify's inert
// DOMParser document. Hoisting its children on removal re-inserts a fresh
// mirror target ahead of the walk, which the engine refills, looping
// forever (DoS) and amplifying output. Dropping its content on removal
// (rather than hoisting) breaks that cascade; the content is a duplicate
// of the option, which is sanitized on its own. See campaign-3 F1/F6.
"selectedcontent",
"style",
"svg",
"template",
"thead",
"title",
"video",
"xmp"
]);
let DATA_URI_TAGS = null;
const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
let URI_SAFE_ATTRIBUTES = null;
@@ -1134,8 +1230,10 @@ function createDOMPurify() {
let IS_EMPTY_INPUT = false;
let ALLOWED_NAMESPACES = null;
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]);
const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(["mi", "mo", "mn", "ms", "mtext"]);
let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]);
let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
let PARSER_MEDIA_TYPE = null;
const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
@@ -1158,14 +1256,32 @@ function createDOMPurify() {
PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
ALLOWED_TAGS = objectHasOwnProperty(cfg, "ALLOWED_TAGS") && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
ALLOWED_ATTR = objectHasOwnProperty(cfg, "ALLOWED_ATTR") && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, "ALLOWED_NAMESPACES") && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
DATA_URI_TAGS = objectHasOwnProperty(cfg, "ADD_DATA_URI_TAGS") && arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
FORBID_CONTENTS = objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
FORBID_TAGS = objectHasOwnProperty(cfg, "FORBID_TAGS") && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
ALLOWED_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, {
transform: transformCaseFunc
});
ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, {
transform: transformCaseFunc
});
ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, {
transform: stringToString
});
URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, {
transform: transformCaseFunc,
base: DEFAULT_URI_SAFE_ATTRIBUTES
});
DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, {
transform: transformCaseFunc,
base: DEFAULT_DATA_URI_TAGS
});
FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, {
transform: transformCaseFunc
});
FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), {
transform: transformCaseFunc
});
FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), {
transform: transformCaseFunc
});
USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
@@ -1184,8 +1300,8 @@ function createDOMPurify() {
IN_PLACE = cfg.IN_PLACE || false;
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ["annotation-xml"]);
MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
CUSTOM_ELEMENT_HANDLING = create(null);
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
@@ -1197,6 +1313,7 @@ function createDOMPurify() {
if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
}
seal(CUSTOM_ELEMENT_HANDLING);
if (SAFE_FOR_TEMPLATES) {
ALLOW_DATA_ATTR = false;
}
@@ -1280,16 +1397,31 @@ function createDOMPurify() {
if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
}
const previousTrustedTypesPolicy = trustedTypesPolicy;
trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
emptyHTML = trustedTypesPolicy.createHTML("");
try {
emptyHTML = _createTrustedHTML("");
} catch (error) {
trustedTypesPolicy = previousTrustedTypesPolicy;
throw error;
}
} else if (cfg.TRUSTED_TYPES_POLICY === null) {
trustedTypesPolicy = void 0;
emptyHTML = "";
} else {
if (trustedTypesPolicy === void 0) {
trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
trustedTypesPolicy = _getDefaultTrustedTypesPolicy();
}
if (trustedTypesPolicy !== null && typeof emptyHTML === "string") {
emptyHTML = trustedTypesPolicy.createHTML("");
if (trustedTypesPolicy && typeof emptyHTML === "string") {
emptyHTML = _createTrustedHTML("");
}
}
if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
ALLOWED_TAGS = clone(ALLOWED_TAGS);
}
if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
ALLOWED_ATTR = clone(ALLOWED_ATTR);
}
if (freeze) {
freeze(cfg);
}
@@ -1297,6 +1429,33 @@ function createDOMPurify() {
};
const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
const _checkSvgNamespace = function _checkSvgNamespace2(tagName, parent, parentTagName) {
if (parent.namespaceURI === HTML_NAMESPACE) {
return tagName === "svg";
}
if (parent.namespaceURI === MATHML_NAMESPACE) {
return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
}
return Boolean(ALL_SVG_TAGS[tagName]);
};
const _checkMathMlNamespace = function _checkMathMlNamespace2(tagName, parent, parentTagName) {
if (parent.namespaceURI === HTML_NAMESPACE) {
return tagName === "math";
}
if (parent.namespaceURI === SVG_NAMESPACE) {
return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
}
return Boolean(ALL_MATHML_TAGS[tagName]);
};
const _checkHtmlNamespace = function _checkHtmlNamespace2(tagName, parent, parentTagName) {
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
return false;
}
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
return false;
}
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
};
const _checkValidNamespace = function _checkValidNamespace2(element) {
let parent = getParentNode(element);
if (!parent || !parent.tagName) {
@@ -1311,31 +1470,13 @@ function createDOMPurify() {
return false;
}
if (element.namespaceURI === SVG_NAMESPACE) {
if (parent.namespaceURI === HTML_NAMESPACE) {
return tagName === "svg";
}
if (parent.namespaceURI === MATHML_NAMESPACE) {
return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
}
return Boolean(ALL_SVG_TAGS[tagName]);
return _checkSvgNamespace(tagName, parent, parentTagName);
}
if (element.namespaceURI === MATHML_NAMESPACE) {
if (parent.namespaceURI === HTML_NAMESPACE) {
return tagName === "math";
}
if (parent.namespaceURI === SVG_NAMESPACE) {
return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
}
return Boolean(ALL_MATHML_TAGS[tagName]);
return _checkMathMlNamespace(tagName, parent, parentTagName);
}
if (element.namespaceURI === HTML_NAMESPACE) {
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
return false;
}
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
return false;
}
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
return _checkHtmlNamespace(tagName, parent, parentTagName);
}
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
return true;
@@ -1350,6 +1491,37 @@ function createDOMPurify() {
getParentNode(node).removeChild(node);
} catch (_) {
remove(node);
if (!getParentNode(node)) {
throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place");
}
}
};
const _neutralizeRoot = function _neutralizeRoot2(root) {
const childNodes = getChildNodes(root);
if (childNodes) {
const snapshot = [];
arrayForEach(childNodes, (child) => {
arrayPush(snapshot, child);
});
arrayForEach(snapshot, (child) => {
try {
remove(child);
} catch (_) {
}
});
}
const attributes = getAttributes(root);
if (attributes) {
for (let i = attributes.length - 1; i >= 0; --i) {
const attribute = attributes[i];
const name = attribute && attribute.name;
if (typeof name === "string") {
try {
root.removeAttribute(name);
} catch (_) {
}
}
}
}
};
const _removeAttribute = function _removeAttribute2(name, element) {
@@ -1379,6 +1551,39 @@ function createDOMPurify() {
}
}
};
const _stripDisallowedAttributes = function _stripDisallowedAttributes2(element) {
const attributes = getAttributes(element);
if (!attributes) {
return;
}
for (let i = attributes.length - 1; i >= 0; --i) {
const attribute = attributes[i];
const name = attribute && attribute.name;
if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) {
continue;
}
try {
element.removeAttribute(name);
} catch (_) {
}
}
};
const _neutralizeSubtree = function _neutralizeSubtree2(root) {
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
if (nodeType === NODE_TYPE.element) {
_stripDisallowedAttributes(node);
}
const childNodes = getChildNodes(node);
if (childNodes) {
for (let i = childNodes.length - 1; i >= 0; --i) {
stack.push(childNodes[i]);
}
}
}
};
const _initDocument = function _initDocument2(dirty) {
let doc = null;
let leadingWhitespace = null;
@@ -1391,7 +1596,7 @@ function createDOMPurify() {
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
}
const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
if (NAMESPACE === HTML_NAMESPACE) {
try {
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
@@ -1423,7 +1628,14 @@ function createDOMPurify() {
null
);
};
const _scrubTemplateExpressions = function _scrubTemplateExpressions2(node) {
const _stripTemplateExpressions = function _stripTemplateExpressions2(value) {
value = stringReplace(value, MUSTACHE_EXPR$1, " ");
value = stringReplace(value, ERB_EXPR$1, " ");
value = stringReplace(value, TMPLIT_EXPR$1, " ");
return value;
};
const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
var _node$querySelectorAl;
node.normalize();
const walker = createNodeIterator.call(
node.ownerDocument || node,
@@ -1434,16 +1646,60 @@ function createDOMPurify() {
);
let currentNode = walker.nextNode();
while (currentNode) {
let data = currentNode.data;
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
data = stringReplace(data, expr, " ");
});
currentNode.data = data;
currentNode.data = _stripTemplateExpressions(currentNode.data);
currentNode = walker.nextNode();
}
const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, "template");
if (templates) {
arrayForEach(templates, (tmpl) => {
if (_isDocumentFragment(tmpl.content)) {
_scrubTemplateExpressions2(tmpl.content);
}
});
}
};
const _isClobbered = function _isClobbered2(element) {
return element instanceof HTMLFormElement && (typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function");
const realTagName = getNodeName ? getNodeName(element) : null;
if (typeof realTagName !== "string") {
return false;
}
if (transformCaseFunc(realTagName) !== "form") {
return false;
}
return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || // Realm-safe NamedNodeMap detection: equality against the cached
// prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
// makes the direct read diverge from the cached read; a clean form
// (same-realm OR foreign-realm) has both reads pointing at the same
// canonical NamedNodeMap.
element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || // NodeType clobbering probe. Cached Node.prototype.nodeType getter
// returns the integer 1 for any Element regardless of realm; direct
// read on a clobbered form (e.g. <input name="nodeType">) returns
// the named child element. Cheap addition — nodeType is read from
// an internal slot, no serialization cost — and removes a residual
// clobbering surface used by several mXSS / PI / comment branches
// in _sanitizeElements that compare currentNode.nodeType directly.
element.nodeType !== getNodeType(element) || // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
// "childNodes" shadows the prototype getter. Direct reads of
// form.childNodes from a clobbered form return the named child
// instead of the real NodeList, so any walk that reads it directly
// skips the form's real children. Compare the direct read to the
// cached Node.prototype getter — when the form's named-property
// getter intercepts the read, the two values differ and we flag
// the form. This catches every clobbering child type (input,
// select, etc.) regardless of whether the named child happens to
// carry a numeric .length, which a typeof-based probe would miss
// (e.g. HTMLSelectElement.length is a defined unsigned-long).
element.childNodes !== getChildNodes(element);
};
const _isDocumentFragment = function _isDocumentFragment2(value) {
if (!getNodeType || typeof value !== "object" || value === null) {
return false;
}
try {
return getNodeType(value) === NODE_TYPE.documentFragment;
} catch (_) {
return false;
}
};
const _isNode = function _isNode2(value) {
if (!getNodeType || typeof value !== "object" || value === null) {
@@ -1456,74 +1712,80 @@ function createDOMPurify() {
}
};
function _executeHooks(hooks2, currentNode, data) {
if (hooks2.length === 0) {
return;
}
arrayForEach(hooks2, (hook) => {
hook.call(DOMPurify, currentNode, data, CONFIG);
});
}
const _isUnsafeNode = function _isUnsafeNode2(currentNode, tagName) {
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {
return true;
}
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
return true;
}
if (currentNode.nodeType === NODE_TYPE.processingInstruction) {
return true;
}
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) {
return true;
}
return false;
};
const _sanitizeDisallowedNode = function _sanitizeDisallowedNode2(currentNode, tagName) {
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
return false;
}
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
return false;
}
}
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
const parentNode = getParentNode(currentNode);
const childNodes = getChildNodes(currentNode);
if (childNodes && parentNode) {
const childCount = childNodes.length;
for (let i = childCount - 1; i >= 0; --i) {
const hoisted = IN_PLACE ? childNodes[i] : cloneNode(childNodes[i], true);
parentNode.insertBefore(hoisted, getNextSibling(currentNode));
}
}
}
_forceRemove(currentNode);
return true;
};
const _sanitizeElements = function _sanitizeElements2(currentNode) {
let content = null;
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
if (_isClobbered(currentNode)) {
_forceRemove(currentNode);
return true;
}
const tagName = transformCaseFunc(currentNode.nodeName);
const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
_executeHooks(hooks.uponSanitizeElement, currentNode, {
tagName,
allowedTags: ALLOWED_TAGS
});
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
_forceRemove(currentNode);
return true;
}
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
_forceRemove(currentNode);
return true;
}
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
_forceRemove(currentNode);
return true;
}
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
if (_isUnsafeNode(currentNode, tagName)) {
_forceRemove(currentNode);
return true;
}
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
return false;
}
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
return false;
}
}
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
const parentNode = getParentNode(currentNode) || currentNode.parentNode;
const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
if (childNodes && parentNode) {
const childCount = childNodes.length;
for (let i = childCount - 1; i >= 0; --i) {
const childClone = cloneNode(childNodes[i], true);
parentNode.insertBefore(childClone, getNextSibling(currentNode));
}
}
}
return _sanitizeDisallowedNode(currentNode, tagName);
}
const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
_forceRemove(currentNode);
return true;
}
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
_forceRemove(currentNode);
return true;
}
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {
_forceRemove(currentNode);
return true;
}
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
content = currentNode.textContent;
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
content = stringReplace(content, expr, " ");
});
const content = _stripTemplateExpressions(currentNode.textContent);
if (currentNode.textContent !== content) {
arrayPush(DOMPurify.removed, {
element: currentNode.cloneNode()
@@ -1542,9 +1804,9 @@ function createDOMPurify() {
return false;
}
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ;
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) ;
else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
else if (!nameIsPermitted) {
if (
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -1569,6 +1831,35 @@ function createDOMPurify() {
const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
};
const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute2(lcTag, lcName, namespaceURI, value) {
if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function" && !namespaceURI) {
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
case "TrustedHTML": {
return _createTrustedHTML(value);
}
case "TrustedScriptURL": {
return _createTrustedScriptURL(value);
}
}
}
return value;
};
const _setAttributeValue = function _setAttributeValue2(currentNode, name, namespaceURI, value) {
try {
if (namespaceURI) {
currentNode.setAttributeNS(namespaceURI, name, value);
} else {
currentNode.setAttribute(name, value);
}
if (_isClobbered(currentNode)) {
_forceRemove(currentNode);
} else {
arrayPop(DOMPurify.removed);
}
} catch (_) {
_removeAttribute(name, currentNode);
}
};
const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
const attributes = currentNode.attributes;
@@ -1583,6 +1874,7 @@ function createDOMPurify() {
forceKeepAttr: void 0
};
let l = attributes.length;
const lcTag = transformCaseFunc(currentNode.nodeName);
while (l--) {
const attr = attributes[l];
const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
@@ -1614,50 +1906,20 @@ function createDOMPurify() {
_removeAttribute(name, currentNode);
continue;
}
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
_removeAttribute(name, currentNode);
continue;
}
if (SAFE_FOR_TEMPLATES) {
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
value = stringReplace(value, expr, " ");
});
value = _stripTemplateExpressions(value);
}
const lcTag = transformCaseFunc(currentNode.nodeName);
if (!_isValidAttribute(lcTag, lcName, value)) {
_removeAttribute(name, currentNode);
continue;
}
if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function") {
if (namespaceURI) ;
else {
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
case "TrustedHTML": {
value = trustedTypesPolicy.createHTML(value);
break;
}
case "TrustedScriptURL": {
value = trustedTypesPolicy.createScriptURL(value);
break;
}
}
}
}
value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
if (value !== initValue) {
try {
if (namespaceURI) {
currentNode.setAttributeNS(namespaceURI, name, value);
} else {
currentNode.setAttribute(name, value);
}
if (_isClobbered(currentNode)) {
_forceRemove(currentNode);
} else {
arrayPop(DOMPurify.removed);
}
} catch (_) {
_removeAttribute(name, currentNode);
}
_setAttributeValue(currentNode, name, namespaceURI, value);
}
}
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
@@ -1670,28 +1932,67 @@ function createDOMPurify() {
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
_sanitizeElements(shadowNode);
_sanitizeAttributes(shadowNode);
if (shadowNode.content instanceof DocumentFragment) {
if (_isDocumentFragment(shadowNode.content)) {
_sanitizeShadowDOM2(shadowNode.content);
}
const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
if (shadowNodeType === NODE_TYPE.element) {
const innerSr = getShadowRoot(shadowNode);
if (_isDocumentFragment(innerSr)) {
_sanitizeAttachedShadowRoots(innerSr);
_sanitizeShadowDOM2(innerSr);
}
}
}
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
};
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
const sr = root.shadowRoot;
_sanitizeAttachedShadowRoots2(sr);
_sanitizeShadowDOM2(sr);
}
const childNodes = root.childNodes;
if (!childNodes) {
return;
}
const snapshot = [];
arrayForEach(childNodes, (child) => {
arrayPush(snapshot, child);
});
for (const child of snapshot) {
_sanitizeAttachedShadowRoots2(child);
const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots2(root) {
const stack = [{
node: root,
shadow: null
}];
while (stack.length > 0) {
const item = stack.pop();
if (item.shadow) {
_sanitizeShadowDOM2(item.shadow);
continue;
}
const node = item.node;
const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
const isElement = nodeType === NODE_TYPE.element;
const childNodes = getChildNodes(node);
if (childNodes) {
for (let i = childNodes.length - 1; i >= 0; --i) {
stack.push({
node: childNodes[i],
shadow: null
});
}
}
if (isElement) {
const rootName = getNodeName ? getNodeName(node) : null;
if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") {
const content = node.content;
if (_isDocumentFragment(content)) {
stack.push({
node: content,
shadow: null
});
}
}
}
if (isElement) {
const sr = getShadowRoot(node);
if (_isDocumentFragment(sr)) {
stack.push({
node: null,
shadow: sr
}, {
node: sr,
shadow: null
});
}
}
}
};
DOMPurify.sanitize = function(dirty) {
@@ -1717,18 +2018,24 @@ function createDOMPurify() {
_parseConfig(cfg);
}
DOMPurify.removed = [];
if (typeof dirty === "string") {
IN_PLACE = false;
}
if (IN_PLACE) {
const nn = dirty.nodeName;
const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
if (inPlace) {
const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
if (typeof nn === "string") {
const tagName = transformCaseFunc(nn);
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
}
}
_sanitizeAttachedShadowRoots2(dirty);
if (_isClobbered(dirty)) {
throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place");
}
try {
_sanitizeAttachedShadowRoots(dirty);
} catch (error) {
_neutralizeRoot(dirty);
throw error;
}
} else if (_isNode(dirty)) {
body = _initDocument("<!---->");
importedNode = body.ownerDocument.importNode(dirty, true);
@@ -1739,11 +2046,11 @@ function createDOMPurify() {
} else {
body.appendChild(importedNode);
}
_sanitizeAttachedShadowRoots2(importedNode);
_sanitizeAttachedShadowRoots(importedNode);
} else {
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
dirty.indexOf("<") === -1) {
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
}
body = _initDocument(dirty);
if (!body) {
@@ -1753,23 +2060,35 @@ function createDOMPurify() {
if (body && FORCE_BODY) {
_forceRemove(body.firstChild);
}
const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
while (currentNode = nodeIterator.nextNode()) {
_sanitizeElements(currentNode);
_sanitizeAttributes(currentNode);
if (currentNode.content instanceof DocumentFragment) {
_sanitizeShadowDOM2(currentNode.content);
const nodeIterator = _createNodeIterator(inPlace ? dirty : body);
try {
while (currentNode = nodeIterator.nextNode()) {
_sanitizeElements(currentNode);
_sanitizeAttributes(currentNode);
if (_isDocumentFragment(currentNode.content)) {
_sanitizeShadowDOM2(currentNode.content);
}
}
} catch (error) {
if (inPlace) {
_neutralizeRoot(dirty);
}
throw error;
}
if (IN_PLACE) {
if (inPlace) {
arrayForEach(DOMPurify.removed, (entry) => {
if (entry.element) {
_neutralizeSubtree(entry.element);
}
});
if (SAFE_FOR_TEMPLATES) {
_scrubTemplateExpressions(dirty);
_scrubTemplateExpressions2(dirty);
}
return dirty;
}
if (RETURN_DOM) {
if (SAFE_FOR_TEMPLATES) {
_scrubTemplateExpressions(body);
_scrubTemplateExpressions2(body);
}
if (RETURN_DOM_FRAGMENT) {
returnNode = createDocumentFragment.call(body.ownerDocument);
@@ -1789,11 +2108,9 @@ function createDOMPurify() {
serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
}
if (SAFE_FOR_TEMPLATES) {
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
serializedHTML = stringReplace(serializedHTML, expr, " ");
});
serializedHTML = _stripTemplateExpressions(serializedHTML);
}
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
};
DOMPurify.setConfig = function() {
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
@@ -1803,6 +2120,8 @@ function createDOMPurify() {
DOMPurify.clearConfig = function() {
CONFIG = null;
SET_CONFIG = false;
trustedTypesPolicy = defaultTrustedTypesPolicy;
emptyHTML = "";
};
DOMPurify.isValidAttribute = function(tag, attr, value) {
if (!CONFIG) {
@@ -2592,13 +2911,8 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
if (this.isProductionMode) {
if (level === "error") {
console.error(`\u274C [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);
if (context && Object.keys(context).length > 0) {
console.error("Error details:", context);
}
} else if (level === "warn") {
console.warn(`\u26A0\uFE0F [SecureChat] ${message}`);
} else if (level === "info" || level === "debug") {
console.log(`[SecureChat] ${message}`, context);
} else {
return;
}
@@ -3883,7 +4197,7 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
// src/transfer/EnhancedSecureFileTransfer.js
var SecureFileTransferContext = class _SecureFileTransferContext {
static #instance = null;
static #contextKey = Symbol("SecureFileTransferContext");
static #contextKey = /* @__PURE__ */ Symbol("SecureFileTransferContext");
static getInstance() {
if (!this.#instance) {
this.#instance = new _SecureFileTransferContext();
@@ -17167,7 +17481,7 @@ Right-click or Ctrl+click to disconnect`,
React.createElement("p", {
key: "subtitle",
className: "text-xs sm:text-sm text-muted hidden sm:block"
}, "End-to-end freedom v4.8.5")
}, "End-to-end freedom v4.8.9")
])
]),
// Status and Controls - Responsive
@@ -18793,6 +19107,6 @@ if (document.readyState === "loading") {
/*! Bundled license information:
dompurify/dist/purify.es.mjs:
(*! @license DOMPurify 3.4.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.4/LICENSE *)
(*! @license DOMPurify 3.4.10 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.10/LICENSE *)
*/
//# sourceMappingURL=app-boot.js.map
+3 -3
View File
File diff suppressed because one or more lines are too long
Vendored
+1 -1
View File
@@ -1820,7 +1820,7 @@ var EnhancedSecureP2PChat = () => {
} catch (error) {
}
}
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.7 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.9 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
const handleBeforeUnload = (event) => {
if (event.type === "beforeunload" && !isTabSwitching) {
if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+5 -1
View File
@@ -5,7 +5,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
try {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
} catch (e) {
throw mod = 0, e;
}
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
+1 -1
View File
File diff suppressed because one or more lines are too long