release: v4.8.9 security hardening patch
- 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:
@@ -4,3 +4,9 @@ node_modules/
|
|||||||
# Local environment noise
|
# Local environment noise
|
||||||
.npm/
|
.npm/
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
.DS_Store
|
||||||
|
**/.DS_Store
|
||||||
|
|
||||||
|
# Operator ICE override holds TURN credentials — never commit it.
|
||||||
|
# Use config/ice-servers.example.js as the template.
|
||||||
|
config/ice-servers.js
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v4.8.9 — Security hardening patch
|
||||||
|
|
||||||
|
This release closes a vulnerable dependency, removes committed TURN credentials, and tightens production logging.
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Upgraded DOMPurify from 3.4.4 to a patched release, resolving a high-severity XSS advisory (GHSA-87xg-pxx2-7hvx) in the incoming-message sanitizer.
|
||||||
|
- Upgraded the `esbuild` build dependency to clear a high-severity advisory in the toolchain. `npm audit` now reports zero vulnerabilities.
|
||||||
|
- Stopped tracking `config/ice-servers.js` (operator TURN credentials) in Git and added `config/ice-servers.example.js` as a template. Operators must rotate any previously committed credentials.
|
||||||
|
- Removed temporary debug branches from the production logger so it no longer prints error context or info/debug payloads — only an opaque error code.
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Updated the supported-release table in `SECURITY.md` to the v4.8.x line.
|
||||||
|
- Synchronized the version string across the header, manifest, README, and in-app initialization message.
|
||||||
|
|
||||||
## v4.8.8 — File transfer consent fix
|
## v4.8.8 — File transfer consent fix
|
||||||
|
|
||||||
This patch completes the mandatory receiver-consent gate for incoming file transfers and resolves a callback ownership conflict that caused every incoming file request to be silently auto-rejected.
|
This patch completes the mandatory receiver-consent gate for incoming file transfers and resolves a callback ownership conflict that caused every incoming file request to be silently auto-rejected.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# SecureBit.chat v4.8.7
|
# SecureBit.chat v4.8.9
|
||||||
|
|
||||||
SecureBit.chat is a browser-based peer-to-peer chat application built on WebRTC and Web Crypto APIs. It is designed for direct encrypted communication, explicit peer verification, and a small operational footprint without account registration or server-side message storage.
|
SecureBit.chat is a browser-based peer-to-peer chat application built on WebRTC and Web Crypto APIs. It is designed for direct encrypted communication, explicit peer verification, and a small operational footprint without account registration or server-side message storage.
|
||||||
|
|
||||||
@@ -15,13 +15,17 @@ SecureBit.chat uses:
|
|||||||
|
|
||||||
A session is not treated as verified until both peers complete the interactive SAS flow. Each user must compare the displayed code with the peer through an out-of-band channel and enter the matching code manually. Three failed SAS attempts terminate the session.
|
A session is not treated as verified until both peers complete the interactive SAS flow. Each user must compare the displayed code with the peer through an out-of-band channel and enter the matching code manually. Three failed SAS attempts terminate the session.
|
||||||
|
|
||||||
## Highlights in v4.8.7
|
## Highlights in v4.8.9
|
||||||
|
|
||||||
- Manual WebRTC setup now preserves pending offer/answer state during slow out-of-band exchange.
|
- Patched a high-severity XSS advisory in the DOMPurify dependency (the message sanitizer) by upgrading to a fixed release.
|
||||||
|
- Operator TURN credentials are no longer committed to the repository; use `config/ice-servers.example.js` as a template.
|
||||||
|
- The production logger no longer prints error context or info/debug output, only opaque error codes.
|
||||||
|
|
||||||
|
This patch release builds on the earlier hardening pass:
|
||||||
|
|
||||||
|
- Manual WebRTC setup preserves pending offer/answer state during slow out-of-band exchange.
|
||||||
- TURN relay fallback can be configured through `config/ice-servers.js` for restrictive networks.
|
- TURN relay fallback can be configured through `config/ice-servers.js` for restrictive networks.
|
||||||
- ICE diagnostics now identify mDNS-only candidate failures without exposing full peer IPs.
|
- ICE diagnostics identify mDNS-only candidate failures without exposing full peer IPs.
|
||||||
|
|
||||||
This patch release strengthens the existing security model with a focused hardening pass:
|
|
||||||
|
|
||||||
- SAS verification is bound to the actual DTLS fingerprint strings of both peers
|
- SAS verification is bound to the actual DTLS fingerprint strings of both peers
|
||||||
- chat sanitization uses DOMPurify-backed text-only output
|
- chat sanitization uses DOMPurify-backed text-only output
|
||||||
|
|||||||
+2
-1
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
| Release | Status | Protocol |
|
| Release | Status | Protocol |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| v4.1.x | Supported | 4.1 |
|
| v4.8.x | Supported | 4.1 |
|
||||||
|
| v4.1.x – v4.7.x | Unsupported | 4.1 |
|
||||||
| earlier releases | Unsupported | legacy |
|
| earlier releases | Unsupported | legacy |
|
||||||
|
|
||||||
Users should run the current supported release line to receive the latest verification, storage, and file-transfer protections.
|
Users should run the current supported release line to receive the latest verification, storage, and file-transfer protections.
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ SecureBit.chat is intended for legitimate private communication, journalism, res
|
|||||||
|
|
||||||
## Current release
|
## Current release
|
||||||
|
|
||||||
- Product release: `v4.8.5`
|
- Product release: `v4.8.9`
|
||||||
- Protocol version: `4.1`
|
- Protocol version: `4.1`
|
||||||
- Last updated: May 17, 2026
|
- Last updated: May 17, 2026
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// SecureBit.chat operator ICE server override — TEMPLATE.
|
||||||
|
//
|
||||||
|
// Copy this file to `config/ice-servers.js` and fill in your own TURN/STUN
|
||||||
|
// servers. The real `config/ice-servers.js` is git-ignored on purpose:
|
||||||
|
// TURN credentials are visible to every browser that loads the page, so they
|
||||||
|
// must never be committed to a public repository. Rotate them from your TURN
|
||||||
|
// provider dashboard if they are ever exposed.
|
||||||
|
//
|
||||||
|
// If this override is absent, the WebRTC manager falls back to the built-in
|
||||||
|
// public STUN defaults (standard mode only — no relay/IP protection).
|
||||||
|
window.SECUREBIT_ICE_SERVERS = [
|
||||||
|
{ urls: 'stun:stun.cloudflare.com:3478' },
|
||||||
|
{
|
||||||
|
urls: [
|
||||||
|
'turn:YOUR_TURN_HOST:3478?transport=udp',
|
||||||
|
'turn:YOUR_TURN_HOST:3478?transport=tcp'
|
||||||
|
],
|
||||||
|
username: 'YOUR_TURN_USERNAME',
|
||||||
|
credential: 'YOUR_TURN_CREDENTIAL'
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// SecureBit.chat operator ICE server override.
|
|
||||||
// Loaded before the WebRTC manager is created. Credentials are visible to browsers;
|
|
||||||
// rotate them from the ExpressTURN dashboard if this file is published publicly.
|
|
||||||
window.SECUREBIT_ICE_SERVERS = [
|
|
||||||
{ urls: 'stun:stun.cloudflare.com:3478' },
|
|
||||||
{ urls: 'stun:stun.expressturn.com:3478' },
|
|
||||||
{
|
|
||||||
urls: [
|
|
||||||
'turn:free.expressturn.com:3478?transport=udp',
|
|
||||||
'turn:free.expressturn.com:3478?transport=tcp'
|
|
||||||
],
|
|
||||||
username: '000000002094555952',
|
|
||||||
credential: 't1oK9Zftes9j7E7hJmsLad9jq1M='
|
|
||||||
}
|
|
||||||
];
|
|
||||||
Vendored
+491
-177
@@ -5,7 +5,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|||||||
var __getProtoOf = Object.getPrototypeOf;
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
var __commonJS = (cb, mod) => function __require() {
|
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) => {
|
var __copyProps = (to, from, except, desc) => {
|
||||||
if (from && typeof from === "object" || typeof from === "function") {
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
@@ -954,7 +958,7 @@ function isRegex(value) {
|
|||||||
return false;
|
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 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 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"]);
|
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 DOCTYPE_NAME = seal(/^html$/i);
|
||||||
var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/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 = {
|
var NODE_TYPE = {
|
||||||
element: 1,
|
element: 1,
|
||||||
|
attribute: 2,
|
||||||
text: 3,
|
text: 3,
|
||||||
|
cdataSection: 4,
|
||||||
|
entityReference: 5,
|
||||||
// Deprecated
|
// Deprecated
|
||||||
progressingInstruction: 7,
|
entityNode: 6,
|
||||||
|
// Deprecated
|
||||||
|
processingInstruction: 7,
|
||||||
comment: 8,
|
comment: 8,
|
||||||
document: 9
|
document: 9,
|
||||||
|
documentType: 10,
|
||||||
|
documentFragment: 11,
|
||||||
|
notation: 12
|
||||||
|
// Deprecated
|
||||||
};
|
};
|
||||||
var getGlobal = function getGlobal2() {
|
var getGlobal = function getGlobal2() {
|
||||||
return typeof window === "undefined" ? null : window;
|
return typeof window === "undefined" ? null : window;
|
||||||
@@ -1029,10 +1046,13 @@ var _createHooksMap = function _createHooksMap2() {
|
|||||||
uponSanitizeShadowNode: []
|
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() {
|
function createDOMPurify() {
|
||||||
let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
||||||
const DOMPurify = (root) => createDOMPurify(root);
|
const DOMPurify = (root) => createDOMPurify(root);
|
||||||
DOMPurify.version = "3.4.4";
|
DOMPurify.version = "3.4.10";
|
||||||
DOMPurify.removed = [];
|
DOMPurify.removed = [];
|
||||||
if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
|
if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
|
||||||
DOMPurify.isSupported = false;
|
DOMPurify.isSupported = false;
|
||||||
@@ -1041,14 +1061,21 @@ function createDOMPurify() {
|
|||||||
let document2 = window2.document;
|
let document2 = window2.document;
|
||||||
const originalDocument = document2;
|
const originalDocument = document2;
|
||||||
const currentScript = originalDocument.currentScript;
|
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 ElementPrototype = Element.prototype;
|
||||||
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
|
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
|
||||||
const remove = lookupGetter(ElementPrototype, "remove");
|
const remove = lookupGetter(ElementPrototype, "remove");
|
||||||
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
|
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
|
||||||
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
|
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
|
||||||
const getParentNode = lookupGetter(ElementPrototype, "parentNode");
|
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 getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
|
||||||
|
const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
|
||||||
if (typeof HTMLTemplateElement === "function") {
|
if (typeof HTMLTemplateElement === "function") {
|
||||||
const template = document2.createElement("template");
|
const template = document2.createElement("template");
|
||||||
if (template.content && template.content.ownerDocument) {
|
if (template.content && template.content.ownerDocument) {
|
||||||
@@ -1057,6 +1084,39 @@ function createDOMPurify() {
|
|||||||
}
|
}
|
||||||
let trustedTypesPolicy;
|
let trustedTypesPolicy;
|
||||||
let emptyHTML = "";
|
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 _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
|
||||||
const importNode = originalDocument.importNode;
|
const importNode = originalDocument.importNode;
|
||||||
let hooks = _createHooksMap();
|
let hooks = _createHooksMap();
|
||||||
@@ -1122,7 +1182,43 @@ function createDOMPurify() {
|
|||||||
let IN_PLACE = false;
|
let IN_PLACE = false;
|
||||||
let USE_PROFILES = {};
|
let USE_PROFILES = {};
|
||||||
let FORBID_CONTENTS = null;
|
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;
|
let DATA_URI_TAGS = null;
|
||||||
const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
|
const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
|
||||||
let URI_SAFE_ATTRIBUTES = null;
|
let URI_SAFE_ATTRIBUTES = null;
|
||||||
@@ -1134,8 +1230,10 @@ function createDOMPurify() {
|
|||||||
let IS_EMPTY_INPUT = false;
|
let IS_EMPTY_INPUT = false;
|
||||||
let ALLOWED_NAMESPACES = null;
|
let ALLOWED_NAMESPACES = null;
|
||||||
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
||||||
let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
|
const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(["mi", "mo", "mn", "ms", "mtext"]);
|
||||||
let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]);
|
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"]);
|
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
|
||||||
let PARSER_MEDIA_TYPE = null;
|
let PARSER_MEDIA_TYPE = null;
|
||||||
const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
|
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
|
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;
|
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;
|
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_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, {
|
||||||
ALLOWED_ATTR = objectHasOwnProperty(cfg, "ALLOWED_ATTR") && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
transform: transformCaseFunc
|
||||||
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;
|
ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, {
|
||||||
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;
|
transform: transformCaseFunc
|
||||||
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({});
|
ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, {
|
||||||
FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
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;
|
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_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
|
||||||
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
|
||||||
@@ -1184,8 +1300,8 @@ function createDOMPurify() {
|
|||||||
IN_PLACE = cfg.IN_PLACE || false;
|
IN_PLACE = cfg.IN_PLACE || false;
|
||||||
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
|
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;
|
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"]);
|
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({}, ["annotation-xml"]);
|
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);
|
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);
|
CUSTOM_ELEMENT_HANDLING = create(null);
|
||||||
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
||||||
@@ -1197,6 +1313,7 @@ function createDOMPurify() {
|
|||||||
if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
|
if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
|
||||||
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
|
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
|
||||||
}
|
}
|
||||||
|
seal(CUSTOM_ELEMENT_HANDLING);
|
||||||
if (SAFE_FOR_TEMPLATES) {
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
ALLOW_DATA_ATTR = false;
|
ALLOW_DATA_ATTR = false;
|
||||||
}
|
}
|
||||||
@@ -1280,16 +1397,31 @@ function createDOMPurify() {
|
|||||||
if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
|
if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
|
||||||
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
|
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
|
||||||
}
|
}
|
||||||
|
const previousTrustedTypesPolicy = trustedTypesPolicy;
|
||||||
trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
|
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 {
|
} else {
|
||||||
if (trustedTypesPolicy === void 0) {
|
if (trustedTypesPolicy === void 0) {
|
||||||
trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
|
trustedTypesPolicy = _getDefaultTrustedTypesPolicy();
|
||||||
}
|
}
|
||||||
if (trustedTypesPolicy !== null && typeof emptyHTML === "string") {
|
if (trustedTypesPolicy && typeof emptyHTML === "string") {
|
||||||
emptyHTML = trustedTypesPolicy.createHTML("");
|
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) {
|
if (freeze) {
|
||||||
freeze(cfg);
|
freeze(cfg);
|
||||||
}
|
}
|
||||||
@@ -1297,6 +1429,33 @@ function createDOMPurify() {
|
|||||||
};
|
};
|
||||||
const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
|
const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
|
||||||
const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
|
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) {
|
const _checkValidNamespace = function _checkValidNamespace2(element) {
|
||||||
let parent = getParentNode(element);
|
let parent = getParentNode(element);
|
||||||
if (!parent || !parent.tagName) {
|
if (!parent || !parent.tagName) {
|
||||||
@@ -1311,31 +1470,13 @@ function createDOMPurify() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (element.namespaceURI === SVG_NAMESPACE) {
|
if (element.namespaceURI === SVG_NAMESPACE) {
|
||||||
if (parent.namespaceURI === HTML_NAMESPACE) {
|
return _checkSvgNamespace(tagName, parent, parentTagName);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
if (element.namespaceURI === MATHML_NAMESPACE) {
|
if (element.namespaceURI === MATHML_NAMESPACE) {
|
||||||
if (parent.namespaceURI === HTML_NAMESPACE) {
|
return _checkMathMlNamespace(tagName, parent, parentTagName);
|
||||||
return tagName === "math";
|
|
||||||
}
|
|
||||||
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
||||||
return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
|
|
||||||
}
|
|
||||||
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
||||||
}
|
}
|
||||||
if (element.namespaceURI === HTML_NAMESPACE) {
|
if (element.namespaceURI === HTML_NAMESPACE) {
|
||||||
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
return _checkHtmlNamespace(tagName, parent, 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]);
|
|
||||||
}
|
}
|
||||||
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
|
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
|
||||||
return true;
|
return true;
|
||||||
@@ -1350,6 +1491,37 @@ function createDOMPurify() {
|
|||||||
getParentNode(node).removeChild(node);
|
getParentNode(node).removeChild(node);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
remove(node);
|
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) {
|
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) {
|
const _initDocument = function _initDocument2(dirty) {
|
||||||
let doc = null;
|
let doc = null;
|
||||||
let leadingWhitespace = null;
|
let leadingWhitespace = null;
|
||||||
@@ -1391,7 +1596,7 @@ function createDOMPurify() {
|
|||||||
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
|
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>";
|
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) {
|
if (NAMESPACE === HTML_NAMESPACE) {
|
||||||
try {
|
try {
|
||||||
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
||||||
@@ -1423,7 +1628,14 @@ function createDOMPurify() {
|
|||||||
null
|
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();
|
node.normalize();
|
||||||
const walker = createNodeIterator.call(
|
const walker = createNodeIterator.call(
|
||||||
node.ownerDocument || node,
|
node.ownerDocument || node,
|
||||||
@@ -1434,16 +1646,60 @@ function createDOMPurify() {
|
|||||||
);
|
);
|
||||||
let currentNode = walker.nextNode();
|
let currentNode = walker.nextNode();
|
||||||
while (currentNode) {
|
while (currentNode) {
|
||||||
let data = currentNode.data;
|
currentNode.data = _stripTemplateExpressions(currentNode.data);
|
||||||
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
|
|
||||||
data = stringReplace(data, expr, " ");
|
|
||||||
});
|
|
||||||
currentNode.data = data;
|
|
||||||
currentNode = walker.nextNode();
|
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) {
|
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) {
|
const _isNode = function _isNode2(value) {
|
||||||
if (!getNodeType || typeof value !== "object" || value === null) {
|
if (!getNodeType || typeof value !== "object" || value === null) {
|
||||||
@@ -1456,74 +1712,80 @@ function createDOMPurify() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
function _executeHooks(hooks2, currentNode, data) {
|
function _executeHooks(hooks2, currentNode, data) {
|
||||||
|
if (hooks2.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
arrayForEach(hooks2, (hook) => {
|
arrayForEach(hooks2, (hook) => {
|
||||||
hook.call(DOMPurify, currentNode, data, CONFIG);
|
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) {
|
const _sanitizeElements = function _sanitizeElements2(currentNode) {
|
||||||
let content = null;
|
|
||||||
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
||||||
if (_isClobbered(currentNode)) {
|
if (_isClobbered(currentNode)) {
|
||||||
_forceRemove(currentNode);
|
_forceRemove(currentNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const tagName = transformCaseFunc(currentNode.nodeName);
|
const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
|
||||||
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
||||||
tagName,
|
tagName,
|
||||||
allowedTags: ALLOWED_TAGS
|
allowedTags: ALLOWED_TAGS
|
||||||
});
|
});
|
||||||
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
|
if (_isUnsafeNode(currentNode, tagName)) {
|
||||||
_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)) {
|
|
||||||
_forceRemove(currentNode);
|
_forceRemove(currentNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
||||||
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
return _sanitizeDisallowedNode(currentNode, tagName);
|
||||||
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
}
|
||||||
return false;
|
const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
|
||||||
}
|
if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_forceRemove(currentNode);
|
_forceRemove(currentNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {
|
||||||
_forceRemove(currentNode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
|
|
||||||
_forceRemove(currentNode);
|
_forceRemove(currentNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
||||||
content = currentNode.textContent;
|
const content = _stripTemplateExpressions(currentNode.textContent);
|
||||||
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
|
|
||||||
content = stringReplace(content, expr, " ");
|
|
||||||
});
|
|
||||||
if (currentNode.textContent !== content) {
|
if (currentNode.textContent !== content) {
|
||||||
arrayPush(DOMPurify.removed, {
|
arrayPush(DOMPurify.removed, {
|
||||||
element: currentNode.cloneNode()
|
element: currentNode.cloneNode()
|
||||||
@@ -1542,9 +1804,9 @@ function createDOMPurify() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
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 (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
|
||||||
else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
|
else if (!nameIsPermitted) {
|
||||||
if (
|
if (
|
||||||
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
// 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
|
// 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) {
|
const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
|
||||||
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, 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) {
|
const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
|
||||||
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
||||||
const attributes = currentNode.attributes;
|
const attributes = currentNode.attributes;
|
||||||
@@ -1583,6 +1874,7 @@ function createDOMPurify() {
|
|||||||
forceKeepAttr: void 0
|
forceKeepAttr: void 0
|
||||||
};
|
};
|
||||||
let l = attributes.length;
|
let l = attributes.length;
|
||||||
|
const lcTag = transformCaseFunc(currentNode.nodeName);
|
||||||
while (l--) {
|
while (l--) {
|
||||||
const attr = attributes[l];
|
const attr = attributes[l];
|
||||||
const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
|
const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
|
||||||
@@ -1614,50 +1906,20 @@ function createDOMPurify() {
|
|||||||
_removeAttribute(name, currentNode);
|
_removeAttribute(name, currentNode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
|
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
|
||||||
_removeAttribute(name, currentNode);
|
_removeAttribute(name, currentNode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (SAFE_FOR_TEMPLATES) {
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
|
value = _stripTemplateExpressions(value);
|
||||||
value = stringReplace(value, expr, " ");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
||||||
if (!_isValidAttribute(lcTag, lcName, value)) {
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
||||||
_removeAttribute(name, currentNode);
|
_removeAttribute(name, currentNode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function") {
|
value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
|
||||||
if (namespaceURI) ;
|
|
||||||
else {
|
|
||||||
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
||||||
case "TrustedHTML": {
|
|
||||||
value = trustedTypesPolicy.createHTML(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "TrustedScriptURL": {
|
|
||||||
value = trustedTypesPolicy.createScriptURL(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value !== initValue) {
|
if (value !== initValue) {
|
||||||
try {
|
_setAttributeValue(currentNode, name, namespaceURI, value);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
||||||
@@ -1670,28 +1932,67 @@ function createDOMPurify() {
|
|||||||
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
|
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
|
||||||
_sanitizeElements(shadowNode);
|
_sanitizeElements(shadowNode);
|
||||||
_sanitizeAttributes(shadowNode);
|
_sanitizeAttributes(shadowNode);
|
||||||
if (shadowNode.content instanceof DocumentFragment) {
|
if (_isDocumentFragment(shadowNode.content)) {
|
||||||
_sanitizeShadowDOM2(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);
|
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
||||||
};
|
};
|
||||||
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
|
const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots2(root) {
|
||||||
if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
|
const stack = [{
|
||||||
const sr = root.shadowRoot;
|
node: root,
|
||||||
_sanitizeAttachedShadowRoots2(sr);
|
shadow: null
|
||||||
_sanitizeShadowDOM2(sr);
|
}];
|
||||||
}
|
while (stack.length > 0) {
|
||||||
const childNodes = root.childNodes;
|
const item = stack.pop();
|
||||||
if (!childNodes) {
|
if (item.shadow) {
|
||||||
return;
|
_sanitizeShadowDOM2(item.shadow);
|
||||||
}
|
continue;
|
||||||
const snapshot = [];
|
}
|
||||||
arrayForEach(childNodes, (child) => {
|
const node = item.node;
|
||||||
arrayPush(snapshot, child);
|
const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
|
||||||
});
|
const isElement = nodeType === NODE_TYPE.element;
|
||||||
for (const child of snapshot) {
|
const childNodes = getChildNodes(node);
|
||||||
_sanitizeAttachedShadowRoots2(child);
|
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) {
|
DOMPurify.sanitize = function(dirty) {
|
||||||
@@ -1717,18 +2018,24 @@ function createDOMPurify() {
|
|||||||
_parseConfig(cfg);
|
_parseConfig(cfg);
|
||||||
}
|
}
|
||||||
DOMPurify.removed = [];
|
DOMPurify.removed = [];
|
||||||
if (typeof dirty === "string") {
|
const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
|
||||||
IN_PLACE = false;
|
if (inPlace) {
|
||||||
}
|
const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
|
||||||
if (IN_PLACE) {
|
|
||||||
const nn = dirty.nodeName;
|
|
||||||
if (typeof nn === "string") {
|
if (typeof nn === "string") {
|
||||||
const tagName = transformCaseFunc(nn);
|
const tagName = transformCaseFunc(nn);
|
||||||
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
||||||
throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
|
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)) {
|
} else if (_isNode(dirty)) {
|
||||||
body = _initDocument("<!---->");
|
body = _initDocument("<!---->");
|
||||||
importedNode = body.ownerDocument.importNode(dirty, true);
|
importedNode = body.ownerDocument.importNode(dirty, true);
|
||||||
@@ -1739,11 +2046,11 @@ function createDOMPurify() {
|
|||||||
} else {
|
} else {
|
||||||
body.appendChild(importedNode);
|
body.appendChild(importedNode);
|
||||||
}
|
}
|
||||||
_sanitizeAttachedShadowRoots2(importedNode);
|
_sanitizeAttachedShadowRoots(importedNode);
|
||||||
} else {
|
} else {
|
||||||
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
|
||||||
dirty.indexOf("<") === -1) {
|
dirty.indexOf("<") === -1) {
|
||||||
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
|
||||||
}
|
}
|
||||||
body = _initDocument(dirty);
|
body = _initDocument(dirty);
|
||||||
if (!body) {
|
if (!body) {
|
||||||
@@ -1753,23 +2060,35 @@ function createDOMPurify() {
|
|||||||
if (body && FORCE_BODY) {
|
if (body && FORCE_BODY) {
|
||||||
_forceRemove(body.firstChild);
|
_forceRemove(body.firstChild);
|
||||||
}
|
}
|
||||||
const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
|
const nodeIterator = _createNodeIterator(inPlace ? dirty : body);
|
||||||
while (currentNode = nodeIterator.nextNode()) {
|
try {
|
||||||
_sanitizeElements(currentNode);
|
while (currentNode = nodeIterator.nextNode()) {
|
||||||
_sanitizeAttributes(currentNode);
|
_sanitizeElements(currentNode);
|
||||||
if (currentNode.content instanceof DocumentFragment) {
|
_sanitizeAttributes(currentNode);
|
||||||
_sanitizeShadowDOM2(currentNode.content);
|
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) {
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
_scrubTemplateExpressions(dirty);
|
_scrubTemplateExpressions2(dirty);
|
||||||
}
|
}
|
||||||
return dirty;
|
return dirty;
|
||||||
}
|
}
|
||||||
if (RETURN_DOM) {
|
if (RETURN_DOM) {
|
||||||
if (SAFE_FOR_TEMPLATES) {
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
_scrubTemplateExpressions(body);
|
_scrubTemplateExpressions2(body);
|
||||||
}
|
}
|
||||||
if (RETURN_DOM_FRAGMENT) {
|
if (RETURN_DOM_FRAGMENT) {
|
||||||
returnNode = createDocumentFragment.call(body.ownerDocument);
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
||||||
@@ -1789,11 +2108,9 @@ function createDOMPurify() {
|
|||||||
serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
|
serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
|
||||||
}
|
}
|
||||||
if (SAFE_FOR_TEMPLATES) {
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
|
serializedHTML = _stripTemplateExpressions(serializedHTML);
|
||||||
serializedHTML = stringReplace(serializedHTML, expr, " ");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
|
||||||
};
|
};
|
||||||
DOMPurify.setConfig = function() {
|
DOMPurify.setConfig = function() {
|
||||||
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
||||||
@@ -1803,6 +2120,8 @@ function createDOMPurify() {
|
|||||||
DOMPurify.clearConfig = function() {
|
DOMPurify.clearConfig = function() {
|
||||||
CONFIG = null;
|
CONFIG = null;
|
||||||
SET_CONFIG = false;
|
SET_CONFIG = false;
|
||||||
|
trustedTypesPolicy = defaultTrustedTypesPolicy;
|
||||||
|
emptyHTML = "";
|
||||||
};
|
};
|
||||||
DOMPurify.isValidAttribute = function(tag, attr, value) {
|
DOMPurify.isValidAttribute = function(tag, attr, value) {
|
||||||
if (!CONFIG) {
|
if (!CONFIG) {
|
||||||
@@ -2592,13 +2911,8 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
if (this.isProductionMode) {
|
if (this.isProductionMode) {
|
||||||
if (level === "error") {
|
if (level === "error") {
|
||||||
console.error(`\u274C [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);
|
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") {
|
} else if (level === "warn") {
|
||||||
console.warn(`\u26A0\uFE0F [SecureChat] ${message}`);
|
console.warn(`\u26A0\uFE0F [SecureChat] ${message}`);
|
||||||
} else if (level === "info" || level === "debug") {
|
|
||||||
console.log(`[SecureChat] ${message}`, context);
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3883,7 +4197,7 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
// src/transfer/EnhancedSecureFileTransfer.js
|
// src/transfer/EnhancedSecureFileTransfer.js
|
||||||
var SecureFileTransferContext = class _SecureFileTransferContext {
|
var SecureFileTransferContext = class _SecureFileTransferContext {
|
||||||
static #instance = null;
|
static #instance = null;
|
||||||
static #contextKey = Symbol("SecureFileTransferContext");
|
static #contextKey = /* @__PURE__ */ Symbol("SecureFileTransferContext");
|
||||||
static getInstance() {
|
static getInstance() {
|
||||||
if (!this.#instance) {
|
if (!this.#instance) {
|
||||||
this.#instance = new _SecureFileTransferContext();
|
this.#instance = new _SecureFileTransferContext();
|
||||||
@@ -17167,7 +17481,7 @@ Right-click or Ctrl+click to disconnect`,
|
|||||||
React.createElement("p", {
|
React.createElement("p", {
|
||||||
key: "subtitle",
|
key: "subtitle",
|
||||||
className: "text-xs sm:text-sm text-muted hidden sm:block"
|
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
|
// Status and Controls - Responsive
|
||||||
@@ -18793,6 +19107,6 @@ if (document.readyState === "loading") {
|
|||||||
/*! Bundled license information:
|
/*! Bundled license information:
|
||||||
|
|
||||||
dompurify/dist/purify.es.mjs:
|
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
|
//# sourceMappingURL=app-boot.js.map
|
||||||
|
|||||||
Vendored
+3
-3
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1820,7 +1820,7 @@ var EnhancedSecureP2PChat = () => {
|
|||||||
} catch (error) {
|
} 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) => {
|
const handleBeforeUnload = (event) => {
|
||||||
if (event.type === "beforeunload" && !isTabSwitching) {
|
if (event.type === "beforeunload" && !isTabSwitching) {
|
||||||
if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {
|
if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+5
-1
@@ -5,7 +5,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|||||||
var __getProtoOf = Object.getPrototypeOf;
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
var __commonJS = (cb, mod) => function __require() {
|
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) => {
|
var __copyProps = (to, from, except, desc) => {
|
||||||
if (from && typeof from === "object" || typeof from === "function") {
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+5
-5
@@ -113,7 +113,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- GitHub Pages SEO -->
|
<!-- GitHub Pages SEO -->
|
||||||
<meta name="description" content="SecureBit.chat v4.8.7 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
<meta name="description" content="SecureBit.chat v4.8.9 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
||||||
<meta name="keywords" content="P2P messenger, ECDH, DTLS, SAS, encryption, WebRTC, privacy, ASN.1 validation, military-grade security, 18-layer defense, MITM protection, PFS">
|
<meta name="keywords" content="P2P messenger, ECDH, DTLS, SAS, encryption, WebRTC, privacy, ASN.1 validation, military-grade security, 18-layer defense, MITM protection, PFS">
|
||||||
<meta name="author" content="Volodymyr">
|
<meta name="author" content="Volodymyr">
|
||||||
<link rel="canonical" href="https://github.com/SecureBitChat/securebit-chat/">
|
<link rel="canonical" href="https://github.com/SecureBitChat/securebit-chat/">
|
||||||
@@ -148,13 +148,13 @@
|
|||||||
<!-- Update Manager - система принудительного обновления -->
|
<!-- Update Manager - система принудительного обновления -->
|
||||||
<script src="src/utils/updateManager.js"></script>
|
<script src="src/utils/updateManager.js"></script>
|
||||||
<script type="module" src="src/components/UpdateChecker.jsx"></script>
|
<script type="module" src="src/components/UpdateChecker.jsx"></script>
|
||||||
<script type="module" src="dist/qr-local.js?v=1779848383991"></script>
|
<script type="module" src="dist/qr-local.js?v=1781550335673"></script>
|
||||||
<script type="module" src="src/components/QRScanner.js?v=1779848383991"></script>
|
<script type="module" src="src/components/QRScanner.js?v=1781550335673"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="dist/app-boot.js?v=1779848383991"></script>
|
<script type="module" src="dist/app-boot.js?v=1781550335673"></script>
|
||||||
<script type="module" src="dist/app.js?v=1779848383991"></script>
|
<script type="module" src="dist/app.js?v=1781550335673"></script>
|
||||||
|
|
||||||
<script src="src/scripts/pwa-register.js"></script>
|
<script src="src/scripts/pwa-register.js"></script>
|
||||||
<script src="./src/pwa/install-prompt.js" type="module"></script>
|
<script src="./src/pwa/install-prompt.js" type="module"></script>
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "SecureBit.chat v4.8.7 - ECDH + DTLS + SAS",
|
"name": "SecureBit.chat v4.8.9 - ECDH + DTLS + SAS",
|
||||||
"short_name": "SecureBit",
|
"short_name": "SecureBit",
|
||||||
"description": "P2P messenger with ECDH + DTLS + SAS security, military-grade cryptography and Lightning Network payments",
|
"description": "P2P messenger with ECDH + DTLS + SAS security, military-grade cryptography and Lightning Network payments",
|
||||||
"start_url": "./",
|
"start_url": "./",
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"version": "1779848383991",
|
"version": "1781550335673",
|
||||||
"buildVersion": "1779848383991",
|
"buildVersion": "1781550335673",
|
||||||
"appVersion": "4.8.8",
|
"appVersion": "4.8.9",
|
||||||
"buildTime": "2026-05-27T02:19:44.033Z",
|
"buildTime": "2026-06-15T19:05:35.714Z",
|
||||||
"buildId": "1779848383991-2468cb4",
|
"buildId": "1781550335673-d11f250",
|
||||||
"gitHash": "2468cb4",
|
"gitHash": "d11f250",
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"generatedAt": "2026-05-27T02:19:44.035Z"
|
"generatedAt": "2026-06-15T19:05:35.717Z"
|
||||||
}
|
}
|
||||||
Generated
+113
-113
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "securebit-chat",
|
"name": "securebit-chat",
|
||||||
"version": "4.8.7",
|
"version": "4.8.9",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "securebit-chat",
|
"name": "securebit-chat",
|
||||||
"version": "4.8.7",
|
"version": "4.8.9",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64-js": "1.5.1",
|
"base64-js": "1.5.1",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"qrcode": "1.5.4"
|
"qrcode": "1.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "0.25.9",
|
"esbuild": "^0.28.1",
|
||||||
"jsdom": "^28.1.0",
|
"jsdom": "^28.1.0",
|
||||||
"tailwindcss": "3.4.17"
|
"tailwindcss": "3.4.17"
|
||||||
}
|
}
|
||||||
@@ -255,9 +255,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
|
||||||
"integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
|
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -272,9 +272,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm": {
|
"node_modules/@esbuild/android-arm": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
|
||||||
"integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
|
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -289,9 +289,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm64": {
|
"node_modules/@esbuild/android-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
|
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -306,9 +306,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-x64": {
|
"node_modules/@esbuild/android-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
|
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -323,9 +323,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-arm64": {
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
|
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -340,9 +340,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-x64": {
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
|
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -357,9 +357,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-arm64": {
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
|
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -374,9 +374,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-x64": {
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
|
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -391,9 +391,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm": {
|
"node_modules/@esbuild/linux-arm": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
|
||||||
"integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
|
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -408,9 +408,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm64": {
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
|
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -425,9 +425,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ia32": {
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
|
||||||
"integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
|
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -442,9 +442,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-loong64": {
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
|
||||||
"integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
|
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -459,9 +459,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-mips64el": {
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
|
||||||
"integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
|
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
@@ -476,9 +476,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ppc64": {
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
|
||||||
"integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
|
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -493,9 +493,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-riscv64": {
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
|
||||||
"integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
|
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -510,9 +510,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-s390x": {
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
|
||||||
"integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
|
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -527,9 +527,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-x64": {
|
"node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
|
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -544,9 +544,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-arm64": {
|
"node_modules/@esbuild/netbsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
|
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -561,9 +561,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-x64": {
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
|
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -578,9 +578,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-arm64": {
|
"node_modules/@esbuild/openbsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
|
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -595,9 +595,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-x64": {
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
|
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -612,9 +612,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openharmony-arm64": {
|
"node_modules/@esbuild/openharmony-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
|
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -629,9 +629,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/sunos-x64": {
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
|
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -646,9 +646,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-arm64": {
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
|
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -663,9 +663,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-ia32": {
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
|
||||||
"integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
|
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -680,9 +680,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-x64": {
|
"node_modules/@esbuild/win32-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
|
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1292,9 +1292,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.4.4",
|
"version": "3.4.10",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.10.tgz",
|
||||||
"integrity": "sha512-r8K7KGKEcztXfA/nfabSYB2hg9tDphORJTdf8xprN/luSLGmNhOBN8dm1/SYjqLLet6YUFEXOcrdTuwryp/Bew==",
|
"integrity": "sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==",
|
||||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@types/trusted-types": "^2.0.7"
|
"@types/trusted-types": "^2.0.7"
|
||||||
@@ -1327,9 +1327,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.25.9",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||||
"integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
|
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -1340,32 +1340,32 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/aix-ppc64": "0.25.9",
|
"@esbuild/aix-ppc64": "0.28.1",
|
||||||
"@esbuild/android-arm": "0.25.9",
|
"@esbuild/android-arm": "0.28.1",
|
||||||
"@esbuild/android-arm64": "0.25.9",
|
"@esbuild/android-arm64": "0.28.1",
|
||||||
"@esbuild/android-x64": "0.25.9",
|
"@esbuild/android-x64": "0.28.1",
|
||||||
"@esbuild/darwin-arm64": "0.25.9",
|
"@esbuild/darwin-arm64": "0.28.1",
|
||||||
"@esbuild/darwin-x64": "0.25.9",
|
"@esbuild/darwin-x64": "0.28.1",
|
||||||
"@esbuild/freebsd-arm64": "0.25.9",
|
"@esbuild/freebsd-arm64": "0.28.1",
|
||||||
"@esbuild/freebsd-x64": "0.25.9",
|
"@esbuild/freebsd-x64": "0.28.1",
|
||||||
"@esbuild/linux-arm": "0.25.9",
|
"@esbuild/linux-arm": "0.28.1",
|
||||||
"@esbuild/linux-arm64": "0.25.9",
|
"@esbuild/linux-arm64": "0.28.1",
|
||||||
"@esbuild/linux-ia32": "0.25.9",
|
"@esbuild/linux-ia32": "0.28.1",
|
||||||
"@esbuild/linux-loong64": "0.25.9",
|
"@esbuild/linux-loong64": "0.28.1",
|
||||||
"@esbuild/linux-mips64el": "0.25.9",
|
"@esbuild/linux-mips64el": "0.28.1",
|
||||||
"@esbuild/linux-ppc64": "0.25.9",
|
"@esbuild/linux-ppc64": "0.28.1",
|
||||||
"@esbuild/linux-riscv64": "0.25.9",
|
"@esbuild/linux-riscv64": "0.28.1",
|
||||||
"@esbuild/linux-s390x": "0.25.9",
|
"@esbuild/linux-s390x": "0.28.1",
|
||||||
"@esbuild/linux-x64": "0.25.9",
|
"@esbuild/linux-x64": "0.28.1",
|
||||||
"@esbuild/netbsd-arm64": "0.25.9",
|
"@esbuild/netbsd-arm64": "0.28.1",
|
||||||
"@esbuild/netbsd-x64": "0.25.9",
|
"@esbuild/netbsd-x64": "0.28.1",
|
||||||
"@esbuild/openbsd-arm64": "0.25.9",
|
"@esbuild/openbsd-arm64": "0.28.1",
|
||||||
"@esbuild/openbsd-x64": "0.25.9",
|
"@esbuild/openbsd-x64": "0.28.1",
|
||||||
"@esbuild/openharmony-arm64": "0.25.9",
|
"@esbuild/openharmony-arm64": "0.28.1",
|
||||||
"@esbuild/sunos-x64": "0.25.9",
|
"@esbuild/sunos-x64": "0.28.1",
|
||||||
"@esbuild/win32-arm64": "0.25.9",
|
"@esbuild/win32-arm64": "0.28.1",
|
||||||
"@esbuild/win32-ia32": "0.25.9",
|
"@esbuild/win32-ia32": "0.28.1",
|
||||||
"@esbuild/win32-x64": "0.25.9"
|
"@esbuild/win32-x64": "0.28.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "securebit-chat",
|
"name": "securebit-chat",
|
||||||
"version": "4.8.8",
|
"version": "4.8.9",
|
||||||
"description": "Secure P2P Communication Application with End-to-End Encryption",
|
"description": "Secure P2P Communication Application with End-to-End Encryption",
|
||||||
"main": "index.html",
|
"main": "index.html",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"author": "SecureBit Team",
|
"author": "SecureBit Team",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "0.25.9",
|
"esbuild": "^0.28.1",
|
||||||
"jsdom": "^28.1.0",
|
"jsdom": "^28.1.0",
|
||||||
"tailwindcss": "3.4.17"
|
"tailwindcss": "3.4.17"
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -2018,7 +2018,7 @@ import { installDebugWindowHooks } from './utils/debugWindowHooks.js';
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) => {
|
const handleBeforeUnload = (event) => {
|
||||||
if (event.type === 'beforeunload' && !isTabSwitching) {
|
if (event.type === 'beforeunload' && !isTabSwitching) {
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ const EnhancedMinimalHeader = ({
|
|||||||
React.createElement('p', {
|
React.createElement('p', {
|
||||||
key: 'subtitle',
|
key: 'subtitle',
|
||||||
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
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')
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
|||||||
@@ -973,20 +973,13 @@ class EnhancedSecureCryptoUtils {
|
|||||||
// Production-safe console output
|
// Production-safe console output
|
||||||
if (this.isProductionMode) {
|
if (this.isProductionMode) {
|
||||||
if (level === 'error') {
|
if (level === 'error') {
|
||||||
// В production показываем только код ошибки без деталей
|
// In production expose only an opaque error code, never the context.
|
||||||
console.error(`❌ [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);
|
console.error(`❌ [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);
|
||||||
// Временно показываем детали для отладки
|
|
||||||
if (context && Object.keys(context).length > 0) {
|
|
||||||
console.error('Error details:', context);
|
|
||||||
}
|
|
||||||
} else if (level === 'warn') {
|
} else if (level === 'warn') {
|
||||||
// В production показываем только предупреждение без контекста
|
// Warning text only, no context payload.
|
||||||
console.warn(`⚠️ [SecureChat] ${message}`);
|
console.warn(`⚠️ [SecureChat] ${message}`);
|
||||||
} else if (level === 'info' || level === 'debug') {
|
|
||||||
// Временно показываем info/debug логи для отладки
|
|
||||||
console.log(`[SecureChat] ${message}`, context);
|
|
||||||
} else {
|
} else {
|
||||||
// В production не показываем другие логи
|
// info/debug and any other level: suppressed entirely in production.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user