@microsoft/omnichannel-chat-widget 1.8.4-main.ffa5cbb → 1.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/common/utils/xssUtils.js +23 -51
- package/lib/cjs/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +0 -1
- package/lib/esm/common/utils/xssUtils.js +23 -51
- package/lib/esm/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +1 -2
- package/lib/types/common/utils/xssUtils.d.ts +5 -21
- package/package.json +3 -3
|
@@ -7,70 +7,42 @@ exports.detectAndCleanXSS = void 0;
|
|
|
7
7
|
var _dompurify = _interopRequireDefault(require("dompurify"));
|
|
8
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Sanitizes text input and detects XSS attack patterns.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* against various XSS techniques including script injection, event handler injection, style-based
|
|
15
|
-
* attacks, and encoded payloads.
|
|
12
|
+
* Sanitizes first with DOMPurify, then checks for malicious patterns in both
|
|
13
|
+
* the original and sanitized text to catch mutation XSS attacks.
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
20
|
-
* - Script tags (<script>)
|
|
21
|
-
* - CSS expression() functions
|
|
22
|
-
* - CSS url() functions
|
|
23
|
-
* - Position-based CSS attacks (position: fixed/absolute)
|
|
24
|
-
* - VBScript protocol URLs
|
|
25
|
-
* - Data URLs with HTML content
|
|
26
|
-
* - Fragment identifiers with escaped quotes
|
|
27
|
-
* - HTML entity-encoded angle brackets
|
|
28
|
-
*
|
|
29
|
-
* @param text - The input text to be analyzed and sanitized
|
|
30
|
-
* @returns An object containing:
|
|
31
|
-
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
32
|
-
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
15
|
+
* @param text - Input text to sanitize
|
|
16
|
+
* @returns Object with cleanText (sanitized) and isXSSDetected flag
|
|
33
17
|
*/
|
|
34
18
|
const detectAndCleanXSS = text => {
|
|
35
|
-
//
|
|
36
|
-
const xssPatterns = [/javascript\s*:/gi,
|
|
37
|
-
// JavaScript protocol URLs (with optional spaces)
|
|
38
|
-
/vbscript\s*:/gi,
|
|
39
|
-
// VBScript protocol URLs (with optional spaces)
|
|
40
|
-
/on\w+\s*=/gi,
|
|
41
|
-
// HTML event handlers (onmouseover, onclick, onload, etc.)
|
|
42
|
-
/<\s*script/gi,
|
|
43
|
-
// Script tag opening (with optional spaces)
|
|
44
|
-
/expression\s*\(/gi,
|
|
45
|
-
// CSS expression() function (IE-specific)
|
|
46
|
-
/url\s*\(/gi,
|
|
47
|
-
// CSS url() function
|
|
48
|
-
/style\s*=.*position\s*:\s*fixed/gi,
|
|
49
|
-
// CSS position fixed attacks
|
|
50
|
-
/style\s*=.*position\s*:\s*absolute/gi,
|
|
51
|
-
// CSS position absolute attacks
|
|
52
|
-
/data\s*:\s*text\s*\/\s*html/gi,
|
|
53
|
-
// Data URLs containing HTML
|
|
54
|
-
/#.*\\"/gi,
|
|
55
|
-
// Fragment identifiers with escaped quotes
|
|
56
|
-
/>.*</gi // HTML entity-encoded angle brackets indicating tag structure
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
// Check if any XSS patterns are detected in the input text
|
|
60
|
-
const isXSSDetected = xssPatterns.some(pattern => pattern.test(text));
|
|
61
|
-
|
|
62
|
-
// Clean the text using DOMPurify with strict config
|
|
19
|
+
// Sanitize first to prevent mutation XSS (e.g., "s<iframe></iframe>tyle" → "style")
|
|
63
20
|
const cleanText = _dompurify.default.sanitize(text, {
|
|
64
21
|
ALLOWED_TAGS: [],
|
|
65
|
-
// No HTML tags allowed in title
|
|
66
22
|
ALLOWED_ATTR: [],
|
|
67
23
|
KEEP_CONTENT: true,
|
|
68
|
-
// Keep text content
|
|
69
24
|
ALLOW_DATA_ATTR: false,
|
|
70
25
|
ALLOW_UNKNOWN_PROTOCOLS: false,
|
|
71
26
|
SANITIZE_DOM: true,
|
|
72
27
|
FORCE_BODY: false
|
|
73
28
|
});
|
|
29
|
+
const contentChanged = text !== cleanText;
|
|
30
|
+
|
|
31
|
+
// Non-global regex patterns to avoid stateful .test() issues
|
|
32
|
+
const xssPatterns = [/javascript\s*:/i, /vbscript\s*:/i, /on\w+\s*=/i,
|
|
33
|
+
// Event handlers
|
|
34
|
+
/<\s*script/i, /<\s*iframe/i, /<\s*object/i, /<\s*embed/i, /<\s*svg/i, /expression\s*\(/i,
|
|
35
|
+
// IE CSS expressions
|
|
36
|
+
/style\s*=.*position\s*:\s*(fixed|absolute)/i, /data\s*:\s*text\s*\/\s*html/i, /#.*\\"/i, /&(lt|gt|#x3c|#60|#x3e|#62);/i,
|
|
37
|
+
// HTML entities
|
|
38
|
+
/&#x?[0-9a-f]+;.*</i, /\u003c.*\u003e/i,
|
|
39
|
+
// Unicode escapes
|
|
40
|
+
/src\s*=\s*["']?\s*javascript:/i, /href\s*=\s*["']?\s*javascript:/i];
|
|
41
|
+
const hasXSSPattern = xssPatterns.some(pattern => {
|
|
42
|
+
return pattern.test(text) || pattern.test(cleanText);
|
|
43
|
+
});
|
|
44
|
+
const hasHTMLStructure = /<[^>]+>/.test(text) && !/<[^>]+>/.test(cleanText);
|
|
45
|
+
const isXSSDetected = contentChanged || hasXSSPattern || hasHTMLStructure;
|
|
74
46
|
return {
|
|
75
47
|
cleanText,
|
|
76
48
|
isXSSDetected
|
|
@@ -122,7 +122,6 @@ const ProactiveChatPaneStateful = props => {
|
|
|
122
122
|
bodyTitleText: state.appStates.proactiveChatStates.proactiveChatBodyTitle ? state.appStates.proactiveChatStates.proactiveChatBodyTitle : proactiveChatProps === null || proactiveChatProps === void 0 ? void 0 : (_proactiveChatProps$c = proactiveChatProps.controlProps) === null || _proactiveChatProps$c === void 0 ? void 0 : _proactiveChatProps$c.bodyTitleText
|
|
123
123
|
};
|
|
124
124
|
(0, _react.useEffect)(() => {
|
|
125
|
-
(0, _utils.setFocusOnElement)(document.getElementById(controlProps.id + "-startbutton"));
|
|
126
125
|
_TelemetryManager.TelemetryTimers.ProactiveChatScreenTimer = (0, _utils.createTimer)();
|
|
127
126
|
const timeoutEvent = setTimeout(() => {
|
|
128
127
|
handleProactiveChatInviteTimeout();
|
|
@@ -1,70 +1,42 @@
|
|
|
1
1
|
import DOMPurify from "dompurify";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Sanitizes text input and detects XSS attack patterns.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* against various XSS techniques including script injection, event handler injection, style-based
|
|
9
|
-
* attacks, and encoded payloads.
|
|
6
|
+
* Sanitizes first with DOMPurify, then checks for malicious patterns in both
|
|
7
|
+
* the original and sanitized text to catch mutation XSS attacks.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
14
|
-
* - Script tags (<script>)
|
|
15
|
-
* - CSS expression() functions
|
|
16
|
-
* - CSS url() functions
|
|
17
|
-
* - Position-based CSS attacks (position: fixed/absolute)
|
|
18
|
-
* - VBScript protocol URLs
|
|
19
|
-
* - Data URLs with HTML content
|
|
20
|
-
* - Fragment identifiers with escaped quotes
|
|
21
|
-
* - HTML entity-encoded angle brackets
|
|
22
|
-
*
|
|
23
|
-
* @param text - The input text to be analyzed and sanitized
|
|
24
|
-
* @returns An object containing:
|
|
25
|
-
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
26
|
-
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
9
|
+
* @param text - Input text to sanitize
|
|
10
|
+
* @returns Object with cleanText (sanitized) and isXSSDetected flag
|
|
27
11
|
*/
|
|
28
12
|
export const detectAndCleanXSS = text => {
|
|
29
|
-
//
|
|
30
|
-
const xssPatterns = [/javascript\s*:/gi,
|
|
31
|
-
// JavaScript protocol URLs (with optional spaces)
|
|
32
|
-
/vbscript\s*:/gi,
|
|
33
|
-
// VBScript protocol URLs (with optional spaces)
|
|
34
|
-
/on\w+\s*=/gi,
|
|
35
|
-
// HTML event handlers (onmouseover, onclick, onload, etc.)
|
|
36
|
-
/<\s*script/gi,
|
|
37
|
-
// Script tag opening (with optional spaces)
|
|
38
|
-
/expression\s*\(/gi,
|
|
39
|
-
// CSS expression() function (IE-specific)
|
|
40
|
-
/url\s*\(/gi,
|
|
41
|
-
// CSS url() function
|
|
42
|
-
/style\s*=.*position\s*:\s*fixed/gi,
|
|
43
|
-
// CSS position fixed attacks
|
|
44
|
-
/style\s*=.*position\s*:\s*absolute/gi,
|
|
45
|
-
// CSS position absolute attacks
|
|
46
|
-
/data\s*:\s*text\s*\/\s*html/gi,
|
|
47
|
-
// Data URLs containing HTML
|
|
48
|
-
/#.*\\"/gi,
|
|
49
|
-
// Fragment identifiers with escaped quotes
|
|
50
|
-
/>.*</gi // HTML entity-encoded angle brackets indicating tag structure
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
// Check if any XSS patterns are detected in the input text
|
|
54
|
-
const isXSSDetected = xssPatterns.some(pattern => pattern.test(text));
|
|
55
|
-
|
|
56
|
-
// Clean the text using DOMPurify with strict config
|
|
13
|
+
// Sanitize first to prevent mutation XSS (e.g., "s<iframe></iframe>tyle" → "style")
|
|
57
14
|
const cleanText = DOMPurify.sanitize(text, {
|
|
58
15
|
ALLOWED_TAGS: [],
|
|
59
|
-
// No HTML tags allowed in title
|
|
60
16
|
ALLOWED_ATTR: [],
|
|
61
17
|
KEEP_CONTENT: true,
|
|
62
|
-
// Keep text content
|
|
63
18
|
ALLOW_DATA_ATTR: false,
|
|
64
19
|
ALLOW_UNKNOWN_PROTOCOLS: false,
|
|
65
20
|
SANITIZE_DOM: true,
|
|
66
21
|
FORCE_BODY: false
|
|
67
22
|
});
|
|
23
|
+
const contentChanged = text !== cleanText;
|
|
24
|
+
|
|
25
|
+
// Non-global regex patterns to avoid stateful .test() issues
|
|
26
|
+
const xssPatterns = [/javascript\s*:/i, /vbscript\s*:/i, /on\w+\s*=/i,
|
|
27
|
+
// Event handlers
|
|
28
|
+
/<\s*script/i, /<\s*iframe/i, /<\s*object/i, /<\s*embed/i, /<\s*svg/i, /expression\s*\(/i,
|
|
29
|
+
// IE CSS expressions
|
|
30
|
+
/style\s*=.*position\s*:\s*(fixed|absolute)/i, /data\s*:\s*text\s*\/\s*html/i, /#.*\\"/i, /&(lt|gt|#x3c|#60|#x3e|#62);/i,
|
|
31
|
+
// HTML entities
|
|
32
|
+
/&#x?[0-9a-f]+;.*</i, /\u003c.*\u003e/i,
|
|
33
|
+
// Unicode escapes
|
|
34
|
+
/src\s*=\s*["']?\s*javascript:/i, /href\s*=\s*["']?\s*javascript:/i];
|
|
35
|
+
const hasXSSPattern = xssPatterns.some(pattern => {
|
|
36
|
+
return pattern.test(text) || pattern.test(cleanText);
|
|
37
|
+
});
|
|
38
|
+
const hasHTMLStructure = /<[^>]+>/.test(text) && !/<[^>]+>/.test(cleanText);
|
|
39
|
+
const isXSSDetected = contentChanged || hasXSSPattern || hasHTMLStructure;
|
|
68
40
|
return {
|
|
69
41
|
cleanText,
|
|
70
42
|
isXSSDetected
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
|
|
2
2
|
import React, { useEffect, useState } from "react";
|
|
3
|
-
import { createTimer
|
|
3
|
+
import { createTimer } from "../../common/utils";
|
|
4
4
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
5
5
|
import { Constants } from "../../common/Constants";
|
|
6
6
|
import { ConversationState } from "../../contexts/common/ConversationState";
|
|
@@ -114,7 +114,6 @@ export const ProactiveChatPaneStateful = props => {
|
|
|
114
114
|
bodyTitleText: state.appStates.proactiveChatStates.proactiveChatBodyTitle ? state.appStates.proactiveChatStates.proactiveChatBodyTitle : proactiveChatProps === null || proactiveChatProps === void 0 ? void 0 : (_proactiveChatProps$c = proactiveChatProps.controlProps) === null || _proactiveChatProps$c === void 0 ? void 0 : _proactiveChatProps$c.bodyTitleText
|
|
115
115
|
};
|
|
116
116
|
useEffect(() => {
|
|
117
|
-
setFocusOnElement(document.getElementById(controlProps.id + "-startbutton"));
|
|
118
117
|
TelemetryTimers.ProactiveChatScreenTimer = createTimer();
|
|
119
118
|
const timeoutEvent = setTimeout(() => {
|
|
120
119
|
handleProactiveChatInviteTimeout();
|
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Sanitizes text input and detects XSS attack patterns.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* against various XSS techniques including script injection, event handler injection, style-based
|
|
7
|
-
* attacks, and encoded payloads.
|
|
4
|
+
* Sanitizes first with DOMPurify, then checks for malicious patterns in both
|
|
5
|
+
* the original and sanitized text to catch mutation XSS attacks.
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
12
|
-
* - Script tags (<script>)
|
|
13
|
-
* - CSS expression() functions
|
|
14
|
-
* - CSS url() functions
|
|
15
|
-
* - Position-based CSS attacks (position: fixed/absolute)
|
|
16
|
-
* - VBScript protocol URLs
|
|
17
|
-
* - Data URLs with HTML content
|
|
18
|
-
* - Fragment identifiers with escaped quotes
|
|
19
|
-
* - HTML entity-encoded angle brackets
|
|
20
|
-
*
|
|
21
|
-
* @param text - The input text to be analyzed and sanitized
|
|
22
|
-
* @returns An object containing:
|
|
23
|
-
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
24
|
-
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
7
|
+
* @param text - Input text to sanitize
|
|
8
|
+
* @returns Object with cleanText (sanitized) and isXSSDetected flag
|
|
25
9
|
*/
|
|
26
10
|
export declare const detectAndCleanXSS: (text: string) => {
|
|
27
11
|
cleanText: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/omnichannel-chat-widget",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
4
4
|
"description": "Microsoft Omnichannel Chat Widget",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"@azure/core-tracing": "^1.2.0",
|
|
88
88
|
"@microsoft/applicationinsights-web": "^3.3.6",
|
|
89
|
-
"@microsoft/omnichannel-chat-components": "1.1.
|
|
90
|
-
"@microsoft/omnichannel-chat-sdk": "^1.11.7-main.
|
|
89
|
+
"@microsoft/omnichannel-chat-components": "1.1.18",
|
|
90
|
+
"@microsoft/omnichannel-chat-sdk": "^1.11.7-main.f31f9b6",
|
|
91
91
|
"@opentelemetry/api": "^1.9.0",
|
|
92
92
|
"abort-controller": "^3",
|
|
93
93
|
"abort-controller-es5": "^2.0.1",
|