@microsoft/omnichannel-chat-components 1.1.15 → 1.1.17-0

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.
@@ -23,7 +23,7 @@ const HiddenTextStyles = {
23
23
  exports.HiddenTextStyles = HiddenTextStyles;
24
24
  const KeyCodes = (_class = class KeyCodes {}, _defineProperty(_class, "ENTER", "Enter"), _defineProperty(_class, "ESCAPE", "Escape"), _defineProperty(_class, "SPACE", "Space"), _defineProperty(_class, "DeclineCallHotKey", "D"), _defineProperty(_class, "AcceptAudioCallHotKey", "S"), _defineProperty(_class, "AcceptVideoCallHotKey", "A"), _defineProperty(_class, "ToggleMicHotKey", "M"), _defineProperty(_class, "ToggleCameraHotKey", "O"), _defineProperty(_class, "EndCallHotKey", "H"), _class);
25
25
  exports.KeyCodes = KeyCodes;
26
- const Regex = (_class2 = class Regex {}, _defineProperty(_class2, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _defineProperty(_class2, "URLRegex", /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi), _class2);
26
+ const Regex = (_class2 = class Regex {}, _defineProperty(_class2, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _defineProperty(_class2, "URLRegex", /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}|mailto:[^\s]+|tel:[^\s]+|sms:[^\s]+)/gi), _class2);
27
27
  exports.Regex = Regex;
28
28
  let ElementType;
29
29
  exports.ElementType = ElementType;
@@ -131,20 +131,48 @@ const addNoreferrerNoopenerTag = htmlNode => {
131
131
  }
132
132
  }
133
133
  }
134
- };
134
+ }; // Escape HTML special characters to prevent XSS in string concatenation
135
+
135
136
 
136
137
  exports.addNoreferrerNoopenerTag = addNoreferrerNoopenerTag;
137
138
 
139
+ const escapeHTML = str => {
140
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
141
+ }; // Escape only characters dangerous in href attribute context
142
+
143
+
144
+ const escapeHrefAttribute = url => {
145
+ return url.replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
146
+ }; // Validate and sanitize URL to prevent javascript: and data: protocols
147
+
148
+
149
+ const isValidURL = url => {
150
+ const trimmedUrl = url.trim().toLowerCase(); // Block dangerous protocols
151
+
152
+ if (trimmedUrl.startsWith("javascript:") || trimmedUrl.startsWith("data:") || trimmedUrl.startsWith("vbscript:") || trimmedUrl.startsWith("file:")) {
153
+ return false;
154
+ } // Allow http, https, protocol-relative URLs, and safe contact schemes
155
+
156
+
157
+ return trimmedUrl.startsWith("http://") || trimmedUrl.startsWith("https://") || trimmedUrl.startsWith("www.") || trimmedUrl.startsWith("mailto:") || trimmedUrl.startsWith("tel:") || trimmedUrl.startsWith("sms:");
158
+ };
159
+
138
160
  const replaceURLWithAnchor = (text, openInNewTab) => {
139
161
  if (text) {
140
162
  const modifiedText = text.replace(_Constants.Regex.URLRegex, function (url) {
141
- if (openInNewTab) {
142
- // eslint-disable-next-line quotes
143
- return '<a href="' + url + '" rel="noreferrer noopener" target="_blank">' + url + '</a>';
144
- } // eslint-disable-next-line quotes
163
+ // Validate URL to prevent dangerous protocols
164
+ if (!isValidURL(url)) {
165
+ return escapeHTML(url); // Return escaped text, not a link
166
+ }
167
+
168
+ const escapedUrl = escapeHrefAttribute(url);
169
+ const displayText = escapeHTML(url);
145
170
 
171
+ if (openInNewTab) {
172
+ return `<a href="${escapedUrl}" rel="noreferrer noopener" target="_blank">${displayText}</a>`;
173
+ }
146
174
 
147
- return '<a href="' + url + '">' + url + '</a>';
175
+ return `<a href="${escapedUrl}">${displayText}</a>`;
148
176
  });
149
177
  return modifiedText;
150
178
  }
@@ -48,7 +48,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
48
48
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
49
49
 
50
50
  function InputValidationPane(props) {
51
- var _props$controlProps, _props$styleProps, _props$styleProps2, _props$styleProps3, _props$styleProps4, _props$controlProps14, _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$styleProps8, _props$styleProps9, _props$styleProps10, _props$styleProps11, _props$styleProps12, _props$styleProps13, _props$styleProps14, _props$styleProps15, _props$styleProps16, _props$controlProps15, _props$styleProps17, _props$styleProps17$c, _props$controlProps16, _props$controlProps17, _props$styleProps18, _props$styleProps18$c, _props$controlProps18, _props$componentOverr, _props$styleProps19, _props$styleProps19$c, _props$controlProps19, _props$controlProps20, _props$componentOverr2, _props$styleProps20, _props$styleProps20$c, _props$controlProps21, _props$controlProps22, _props$componentOverr3, _props$styleProps21, _props$styleProps21$c, _props$controlProps23, _props$controlProps24, _props$controlProps25, _props$componentOverr4, _props$styleProps22, _props$styleProps22$c, _props$controlProps26, _props$controlProps27, _props$controlProps28, _props$styleProps23, _props$styleProps23$c, _props$controlProps29, _props$componentOverr5, _props$styleProps24, _props$styleProps24$c, _props$controlProps30, _props$controlProps31, _props$controlProps32, _props$controlProps33, _props$componentOverr6, _props$styleProps25, _props$styleProps25$c, _props$controlProps34, _props$controlProps35, _props$controlProps36;
51
+ var _props$controlProps, _props$styleProps, _props$styleProps2, _props$styleProps3, _props$styleProps4, _props$controlProps14, _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$styleProps8, _props$styleProps9, _props$styleProps10, _props$styleProps11, _props$styleProps12, _props$styleProps13, _props$styleProps14, _props$styleProps15, _props$styleProps16, _props$controlProps15, _props$styleProps17, _props$styleProps17$c, _props$controlProps16, _props$controlProps17, _props$styleProps18, _props$styleProps18$c, _props$controlProps18, _props$componentOverr, _props$styleProps19, _props$styleProps19$c, _props$controlProps19, _props$controlProps20, _props$componentOverr2, _props$styleProps20, _props$styleProps20$c, _props$controlProps21, _props$controlProps22, _props$componentOverr3, _props$styleProps21, _props$styleProps21$c, _props$controlProps23, _props$controlProps24, _props$controlProps25, _props$componentOverr4, _props$styleProps22, _props$styleProps22$c, _props$controlProps26, _props$controlProps27, _props$styleProps23, _props$styleProps23$c, _props$controlProps28, _props$componentOverr5, _props$styleProps24, _props$styleProps24$c, _props$controlProps29, _props$controlProps30, _props$controlProps31, _props$controlProps32, _props$componentOverr6, _props$styleProps25, _props$styleProps25$c, _props$controlProps33, _props$controlProps34, _props$controlProps35;
52
52
 
53
53
  const elementId = ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.id) ?? _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.id;
54
54
  const [inputValue, setInputValue] = (0, _react2.useState)("");
@@ -247,35 +247,34 @@ function InputValidationPane(props) {
247
247
  })), isInvalidInput && ((0, _decodeComponentString.decodeComponentString)((_props$componentOverr4 = props.componentOverrides) === null || _props$componentOverr4 === void 0 ? void 0 : _props$componentOverr4.invalidInputErrorMessage) || /*#__PURE__*/_react2.default.createElement(_react.Stack, {
248
248
  className: (_props$styleProps22 = props.styleProps) === null || _props$styleProps22 === void 0 ? void 0 : (_props$styleProps22$c = _props$styleProps22.classNames) === null || _props$styleProps22$c === void 0 ? void 0 : _props$styleProps22$c.invalidInputErrorMessageClassName,
249
249
  styles: invalidInputErrorMessageStyles,
250
- "aria-label": ((_props$controlProps26 = props.controlProps) === null || _props$controlProps26 === void 0 ? void 0 : _props$controlProps26.invalidInputErrorMessageText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.invalidInputErrorMessageText,
251
250
  tabIndex: -1,
252
251
  role: "alert",
253
252
  id: elementId + "-invalidinputerrormessage"
254
- }, ((_props$controlProps27 = props.controlProps) === null || _props$controlProps27 === void 0 ? void 0 : _props$controlProps27.invalidInputErrorMessageText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.invalidInputErrorMessageText))), /*#__PURE__*/_react2.default.createElement(_react.Stack, {
255
- horizontal: ((_props$controlProps28 = props.controlProps) === null || _props$controlProps28 === void 0 ? void 0 : _props$controlProps28.isButtonGroupHorizontal) ?? _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.isButtonGroupHorizontal,
253
+ }, ((_props$controlProps26 = props.controlProps) === null || _props$controlProps26 === void 0 ? void 0 : _props$controlProps26.invalidInputErrorMessageText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.invalidInputErrorMessageText))), /*#__PURE__*/_react2.default.createElement(_react.Stack, {
254
+ horizontal: ((_props$controlProps27 = props.controlProps) === null || _props$controlProps27 === void 0 ? void 0 : _props$controlProps27.isButtonGroupHorizontal) ?? _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.isButtonGroupHorizontal,
256
255
  className: (_props$styleProps23 = props.styleProps) === null || _props$styleProps23 === void 0 ? void 0 : (_props$styleProps23$c = _props$styleProps23.classNames) === null || _props$styleProps23$c === void 0 ? void 0 : _props$styleProps23$c.buttonGroupClassName,
257
256
  styles: buttonGroupStyles,
258
257
  tabIndex: -1,
259
258
  id: elementId + "-buttongroup"
260
- }, !((_props$controlProps29 = props.controlProps) !== null && _props$controlProps29 !== void 0 && _props$controlProps29.hideSendButton) && ((0, _decodeComponentString.decodeComponentString)((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.sendButton) || /*#__PURE__*/_react2.default.createElement(_Button.PrimaryButton, {
259
+ }, !((_props$controlProps28 = props.controlProps) !== null && _props$controlProps28 !== void 0 && _props$controlProps28.hideSendButton) && ((0, _decodeComponentString.decodeComponentString)((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.sendButton) || /*#__PURE__*/_react2.default.createElement(_Button.PrimaryButton, {
261
260
  className: (_props$styleProps24 = props.styleProps) === null || _props$styleProps24 === void 0 ? void 0 : (_props$styleProps24$c = _props$styleProps24.classNames) === null || _props$styleProps24$c === void 0 ? void 0 : _props$styleProps24$c.sendButtonClassName,
262
261
  styles: sendButtonStyles,
263
- title: ((_props$controlProps30 = props.controlProps) === null || _props$controlProps30 === void 0 ? void 0 : _props$controlProps30.sendButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonText,
262
+ title: ((_props$controlProps29 = props.controlProps) === null || _props$controlProps29 === void 0 ? void 0 : _props$controlProps29.sendButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonText,
264
263
  tabIndex: 0,
265
264
  disabled: !isSendButtonEnabled,
266
- text: ((_props$controlProps31 = props.controlProps) === null || _props$controlProps31 === void 0 ? void 0 : _props$controlProps31.sendButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonText,
265
+ text: ((_props$controlProps30 = props.controlProps) === null || _props$controlProps30 === void 0 ? void 0 : _props$controlProps30.sendButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonText,
267
266
  onClick: handleSendClick,
268
267
  id: elementId + "-sendbutton",
269
- ariaLabel: ((_props$controlProps32 = props.controlProps) === null || _props$controlProps32 === void 0 ? void 0 : _props$controlProps32.sendButtonAriaLabel) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonAriaLabel
270
- })), !((_props$controlProps33 = props.controlProps) !== null && _props$controlProps33 !== void 0 && _props$controlProps33.hideCancelButton) && ((0, _decodeComponentString.decodeComponentString)((_props$componentOverr6 = props.componentOverrides) === null || _props$componentOverr6 === void 0 ? void 0 : _props$componentOverr6.cancelButton) || /*#__PURE__*/_react2.default.createElement(_Button.DefaultButton, {
268
+ ariaLabel: ((_props$controlProps31 = props.controlProps) === null || _props$controlProps31 === void 0 ? void 0 : _props$controlProps31.sendButtonAriaLabel) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.sendButtonAriaLabel
269
+ })), !((_props$controlProps32 = props.controlProps) !== null && _props$controlProps32 !== void 0 && _props$controlProps32.hideCancelButton) && ((0, _decodeComponentString.decodeComponentString)((_props$componentOverr6 = props.componentOverrides) === null || _props$componentOverr6 === void 0 ? void 0 : _props$componentOverr6.cancelButton) || /*#__PURE__*/_react2.default.createElement(_Button.DefaultButton, {
271
270
  className: (_props$styleProps25 = props.styleProps) === null || _props$styleProps25 === void 0 ? void 0 : (_props$styleProps25$c = _props$styleProps25.classNames) === null || _props$styleProps25$c === void 0 ? void 0 : _props$styleProps25$c.cancelButtonClassName,
272
271
  styles: cancelButtonStyles,
273
- title: ((_props$controlProps34 = props.controlProps) === null || _props$controlProps34 === void 0 ? void 0 : _props$controlProps34.cancelButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonText,
272
+ title: ((_props$controlProps33 = props.controlProps) === null || _props$controlProps33 === void 0 ? void 0 : _props$controlProps33.cancelButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonText,
274
273
  tabIndex: 0,
275
- text: ((_props$controlProps35 = props.controlProps) === null || _props$controlProps35 === void 0 ? void 0 : _props$controlProps35.cancelButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonText,
274
+ text: ((_props$controlProps34 = props.controlProps) === null || _props$controlProps34 === void 0 ? void 0 : _props$controlProps34.cancelButtonText) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonText,
276
275
  onClick: handleCancelClick,
277
276
  id: elementId + "-cancelbutton",
278
- ariaLabel: ((_props$controlProps36 = props.controlProps) === null || _props$controlProps36 === void 0 ? void 0 : _props$controlProps36.cancelButtonAriaLabel) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonAriaLabel
277
+ ariaLabel: ((_props$controlProps35 = props.controlProps) === null || _props$controlProps35 === void 0 ? void 0 : _props$controlProps35.cancelButtonAriaLabel) || _defaultInputValidationPaneControlProps.defaultInputValidationPaneControlProps.cancelButtonAriaLabel
279
278
  })))));
280
279
  }
281
280
 
@@ -13,7 +13,7 @@ export const HiddenTextStyles = {
13
13
  whiteSpace: "nowrap"
14
14
  };
15
15
  export const KeyCodes = (_class = class KeyCodes {}, _defineProperty(_class, "ENTER", "Enter"), _defineProperty(_class, "ESCAPE", "Escape"), _defineProperty(_class, "SPACE", "Space"), _defineProperty(_class, "DeclineCallHotKey", "D"), _defineProperty(_class, "AcceptAudioCallHotKey", "S"), _defineProperty(_class, "AcceptVideoCallHotKey", "A"), _defineProperty(_class, "ToggleMicHotKey", "M"), _defineProperty(_class, "ToggleCameraHotKey", "O"), _defineProperty(_class, "EndCallHotKey", "H"), _class);
16
- export const Regex = (_class2 = class Regex {}, _defineProperty(_class2, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _defineProperty(_class2, "URLRegex", /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi), _class2);
16
+ export const Regex = (_class2 = class Regex {}, _defineProperty(_class2, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _defineProperty(_class2, "URLRegex", /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}|mailto:[^\s]+|tel:[^\s]+|sms:[^\s]+)/gi), _class2);
17
17
  export let ElementType;
18
18
 
19
19
  (function (ElementType) {
@@ -93,17 +93,45 @@ export const addNoreferrerNoopenerTag = htmlNode => {
93
93
  }
94
94
  }
95
95
  }
96
+ }; // Escape HTML special characters to prevent XSS in string concatenation
97
+
98
+ const escapeHTML = str => {
99
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
100
+ }; // Escape only characters dangerous in href attribute context
101
+
102
+
103
+ const escapeHrefAttribute = url => {
104
+ return url.replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
105
+ }; // Validate and sanitize URL to prevent javascript: and data: protocols
106
+
107
+
108
+ const isValidURL = url => {
109
+ const trimmedUrl = url.trim().toLowerCase(); // Block dangerous protocols
110
+
111
+ if (trimmedUrl.startsWith("javascript:") || trimmedUrl.startsWith("data:") || trimmedUrl.startsWith("vbscript:") || trimmedUrl.startsWith("file:")) {
112
+ return false;
113
+ } // Allow http, https, protocol-relative URLs, and safe contact schemes
114
+
115
+
116
+ return trimmedUrl.startsWith("http://") || trimmedUrl.startsWith("https://") || trimmedUrl.startsWith("www.") || trimmedUrl.startsWith("mailto:") || trimmedUrl.startsWith("tel:") || trimmedUrl.startsWith("sms:");
96
117
  };
118
+
97
119
  export const replaceURLWithAnchor = (text, openInNewTab) => {
98
120
  if (text) {
99
121
  const modifiedText = text.replace(Regex.URLRegex, function (url) {
100
- if (openInNewTab) {
101
- // eslint-disable-next-line quotes
102
- return '<a href="' + url + '" rel="noreferrer noopener" target="_blank">' + url + '</a>';
103
- } // eslint-disable-next-line quotes
122
+ // Validate URL to prevent dangerous protocols
123
+ if (!isValidURL(url)) {
124
+ return escapeHTML(url); // Return escaped text, not a link
125
+ }
104
126
 
127
+ const escapedUrl = escapeHrefAttribute(url);
128
+ const displayText = escapeHTML(url);
129
+
130
+ if (openInNewTab) {
131
+ return `<a href="${escapedUrl}" rel="noreferrer noopener" target="_blank">${displayText}</a>`;
132
+ }
105
133
 
106
- return '<a href="' + url + '">' + url + '</a>';
134
+ return `<a href="${escapedUrl}">${displayText}</a>`;
107
135
  });
108
136
  return modifiedText;
109
137
  }
@@ -19,7 +19,7 @@ import { defaultInputValidationPaneTitleStyles } from "./common/default/defaultS
19
19
  import { generateEventName } from "../../common/utils";
20
20
 
21
21
  function InputValidationPane(props) {
22
- var _props$controlProps, _props$styleProps, _props$styleProps2, _props$styleProps3, _props$styleProps4, _props$controlProps14, _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$styleProps8, _props$styleProps9, _props$styleProps10, _props$styleProps11, _props$styleProps12, _props$styleProps13, _props$styleProps14, _props$styleProps15, _props$styleProps16, _props$controlProps15, _props$styleProps17, _props$styleProps17$c, _props$controlProps16, _props$controlProps17, _props$styleProps18, _props$styleProps18$c, _props$controlProps18, _props$componentOverr, _props$styleProps19, _props$styleProps19$c, _props$controlProps19, _props$controlProps20, _props$componentOverr2, _props$styleProps20, _props$styleProps20$c, _props$controlProps21, _props$controlProps22, _props$componentOverr3, _props$styleProps21, _props$styleProps21$c, _props$controlProps23, _props$controlProps24, _props$controlProps25, _props$componentOverr4, _props$styleProps22, _props$styleProps22$c, _props$controlProps26, _props$controlProps27, _props$controlProps28, _props$styleProps23, _props$styleProps23$c, _props$controlProps29, _props$componentOverr5, _props$styleProps24, _props$styleProps24$c, _props$controlProps30, _props$controlProps31, _props$controlProps32, _props$controlProps33, _props$componentOverr6, _props$styleProps25, _props$styleProps25$c, _props$controlProps34, _props$controlProps35, _props$controlProps36;
22
+ var _props$controlProps, _props$styleProps, _props$styleProps2, _props$styleProps3, _props$styleProps4, _props$controlProps14, _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$styleProps8, _props$styleProps9, _props$styleProps10, _props$styleProps11, _props$styleProps12, _props$styleProps13, _props$styleProps14, _props$styleProps15, _props$styleProps16, _props$controlProps15, _props$styleProps17, _props$styleProps17$c, _props$controlProps16, _props$controlProps17, _props$styleProps18, _props$styleProps18$c, _props$controlProps18, _props$componentOverr, _props$styleProps19, _props$styleProps19$c, _props$controlProps19, _props$controlProps20, _props$componentOverr2, _props$styleProps20, _props$styleProps20$c, _props$controlProps21, _props$controlProps22, _props$componentOverr3, _props$styleProps21, _props$styleProps21$c, _props$controlProps23, _props$controlProps24, _props$controlProps25, _props$componentOverr4, _props$styleProps22, _props$styleProps22$c, _props$controlProps26, _props$controlProps27, _props$styleProps23, _props$styleProps23$c, _props$controlProps28, _props$componentOverr5, _props$styleProps24, _props$styleProps24$c, _props$controlProps29, _props$controlProps30, _props$controlProps31, _props$controlProps32, _props$componentOverr6, _props$styleProps25, _props$styleProps25$c, _props$controlProps33, _props$controlProps34, _props$controlProps35;
23
23
 
24
24
  const elementId = ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.id) ?? defaultInputValidationPaneControlProps.id;
25
25
  const [inputValue, setInputValue] = useState("");
@@ -214,35 +214,34 @@ function InputValidationPane(props) {
214
214
  })), isInvalidInput && (decodeComponentString((_props$componentOverr4 = props.componentOverrides) === null || _props$componentOverr4 === void 0 ? void 0 : _props$componentOverr4.invalidInputErrorMessage) || /*#__PURE__*/React.createElement(Stack, {
215
215
  className: (_props$styleProps22 = props.styleProps) === null || _props$styleProps22 === void 0 ? void 0 : (_props$styleProps22$c = _props$styleProps22.classNames) === null || _props$styleProps22$c === void 0 ? void 0 : _props$styleProps22$c.invalidInputErrorMessageClassName,
216
216
  styles: invalidInputErrorMessageStyles,
217
- "aria-label": ((_props$controlProps26 = props.controlProps) === null || _props$controlProps26 === void 0 ? void 0 : _props$controlProps26.invalidInputErrorMessageText) || defaultInputValidationPaneControlProps.invalidInputErrorMessageText,
218
217
  tabIndex: -1,
219
218
  role: "alert",
220
219
  id: elementId + "-invalidinputerrormessage"
221
- }, ((_props$controlProps27 = props.controlProps) === null || _props$controlProps27 === void 0 ? void 0 : _props$controlProps27.invalidInputErrorMessageText) || defaultInputValidationPaneControlProps.invalidInputErrorMessageText))), /*#__PURE__*/React.createElement(Stack, {
222
- horizontal: ((_props$controlProps28 = props.controlProps) === null || _props$controlProps28 === void 0 ? void 0 : _props$controlProps28.isButtonGroupHorizontal) ?? defaultInputValidationPaneControlProps.isButtonGroupHorizontal,
220
+ }, ((_props$controlProps26 = props.controlProps) === null || _props$controlProps26 === void 0 ? void 0 : _props$controlProps26.invalidInputErrorMessageText) || defaultInputValidationPaneControlProps.invalidInputErrorMessageText))), /*#__PURE__*/React.createElement(Stack, {
221
+ horizontal: ((_props$controlProps27 = props.controlProps) === null || _props$controlProps27 === void 0 ? void 0 : _props$controlProps27.isButtonGroupHorizontal) ?? defaultInputValidationPaneControlProps.isButtonGroupHorizontal,
223
222
  className: (_props$styleProps23 = props.styleProps) === null || _props$styleProps23 === void 0 ? void 0 : (_props$styleProps23$c = _props$styleProps23.classNames) === null || _props$styleProps23$c === void 0 ? void 0 : _props$styleProps23$c.buttonGroupClassName,
224
223
  styles: buttonGroupStyles,
225
224
  tabIndex: -1,
226
225
  id: elementId + "-buttongroup"
227
- }, !((_props$controlProps29 = props.controlProps) !== null && _props$controlProps29 !== void 0 && _props$controlProps29.hideSendButton) && (decodeComponentString((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.sendButton) || /*#__PURE__*/React.createElement(PrimaryButton, {
226
+ }, !((_props$controlProps28 = props.controlProps) !== null && _props$controlProps28 !== void 0 && _props$controlProps28.hideSendButton) && (decodeComponentString((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.sendButton) || /*#__PURE__*/React.createElement(PrimaryButton, {
228
227
  className: (_props$styleProps24 = props.styleProps) === null || _props$styleProps24 === void 0 ? void 0 : (_props$styleProps24$c = _props$styleProps24.classNames) === null || _props$styleProps24$c === void 0 ? void 0 : _props$styleProps24$c.sendButtonClassName,
229
228
  styles: sendButtonStyles,
230
- title: ((_props$controlProps30 = props.controlProps) === null || _props$controlProps30 === void 0 ? void 0 : _props$controlProps30.sendButtonText) || defaultInputValidationPaneControlProps.sendButtonText,
229
+ title: ((_props$controlProps29 = props.controlProps) === null || _props$controlProps29 === void 0 ? void 0 : _props$controlProps29.sendButtonText) || defaultInputValidationPaneControlProps.sendButtonText,
231
230
  tabIndex: 0,
232
231
  disabled: !isSendButtonEnabled,
233
- text: ((_props$controlProps31 = props.controlProps) === null || _props$controlProps31 === void 0 ? void 0 : _props$controlProps31.sendButtonText) || defaultInputValidationPaneControlProps.sendButtonText,
232
+ text: ((_props$controlProps30 = props.controlProps) === null || _props$controlProps30 === void 0 ? void 0 : _props$controlProps30.sendButtonText) || defaultInputValidationPaneControlProps.sendButtonText,
234
233
  onClick: handleSendClick,
235
234
  id: elementId + "-sendbutton",
236
- ariaLabel: ((_props$controlProps32 = props.controlProps) === null || _props$controlProps32 === void 0 ? void 0 : _props$controlProps32.sendButtonAriaLabel) || defaultInputValidationPaneControlProps.sendButtonAriaLabel
237
- })), !((_props$controlProps33 = props.controlProps) !== null && _props$controlProps33 !== void 0 && _props$controlProps33.hideCancelButton) && (decodeComponentString((_props$componentOverr6 = props.componentOverrides) === null || _props$componentOverr6 === void 0 ? void 0 : _props$componentOverr6.cancelButton) || /*#__PURE__*/React.createElement(DefaultButton, {
235
+ ariaLabel: ((_props$controlProps31 = props.controlProps) === null || _props$controlProps31 === void 0 ? void 0 : _props$controlProps31.sendButtonAriaLabel) || defaultInputValidationPaneControlProps.sendButtonAriaLabel
236
+ })), !((_props$controlProps32 = props.controlProps) !== null && _props$controlProps32 !== void 0 && _props$controlProps32.hideCancelButton) && (decodeComponentString((_props$componentOverr6 = props.componentOverrides) === null || _props$componentOverr6 === void 0 ? void 0 : _props$componentOverr6.cancelButton) || /*#__PURE__*/React.createElement(DefaultButton, {
238
237
  className: (_props$styleProps25 = props.styleProps) === null || _props$styleProps25 === void 0 ? void 0 : (_props$styleProps25$c = _props$styleProps25.classNames) === null || _props$styleProps25$c === void 0 ? void 0 : _props$styleProps25$c.cancelButtonClassName,
239
238
  styles: cancelButtonStyles,
240
- title: ((_props$controlProps34 = props.controlProps) === null || _props$controlProps34 === void 0 ? void 0 : _props$controlProps34.cancelButtonText) || defaultInputValidationPaneControlProps.cancelButtonText,
239
+ title: ((_props$controlProps33 = props.controlProps) === null || _props$controlProps33 === void 0 ? void 0 : _props$controlProps33.cancelButtonText) || defaultInputValidationPaneControlProps.cancelButtonText,
241
240
  tabIndex: 0,
242
- text: ((_props$controlProps35 = props.controlProps) === null || _props$controlProps35 === void 0 ? void 0 : _props$controlProps35.cancelButtonText) || defaultInputValidationPaneControlProps.cancelButtonText,
241
+ text: ((_props$controlProps34 = props.controlProps) === null || _props$controlProps34 === void 0 ? void 0 : _props$controlProps34.cancelButtonText) || defaultInputValidationPaneControlProps.cancelButtonText,
243
242
  onClick: handleCancelClick,
244
243
  id: elementId + "-cancelbutton",
245
- ariaLabel: ((_props$controlProps36 = props.controlProps) === null || _props$controlProps36 === void 0 ? void 0 : _props$controlProps36.cancelButtonAriaLabel) || defaultInputValidationPaneControlProps.cancelButtonAriaLabel
244
+ ariaLabel: ((_props$controlProps35 = props.controlProps) === null || _props$controlProps35 === void 0 ? void 0 : _props$controlProps35.cancelButtonAriaLabel) || defaultInputValidationPaneControlProps.cancelButtonAriaLabel
246
245
  })))));
247
246
  }
248
247
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-components",
3
- "version": "1.1.15",
3
+ "version": "1.1.17-0",
4
4
  "description": "Microsoft Omnichannel Chat Components",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",