From bbbf0362462172773d443b2c33e5d9eed7d0392e Mon Sep 17 00:00:00 2001 From: mgamis-msft Date: Thu, 17 Sep 2026 02:37:55 -0700 Subject: [PATCH 1/3] Fix linkify-it CVE in communication-react dependencies --- common/config/rush/pnpm-lock.yaml | 80 +++++++------------ .../rush/variants/stable/pnpm-lock.yaml | 80 +++++++------------ packages/communication-react/package.json | 3 +- packages/react-components/package.json | 3 +- .../ChatMessage/ChatMessageContent.test.tsx | 36 +++++++++ .../ChatMessage/ChatMessageContent.tsx | 39 +++++---- packages/react-composites/package.json | 3 +- packages/storybook8/package.json | 1 - samples/Chat/package.json | 2 - 9 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 6efb7cc3466..2304df0064c 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -6325,12 +6325,6 @@ packages: '@types/react': 18.3.12 dev: false - /@types/react-linkify@1.0.4: - resolution: {integrity: sha512-NOMw4X3kjvjY0lT5kXQdxZCXpPNi2hOuuqG+Kz+5EOQpi9rDUJJDitdE1j2JRNmrTnNIjrLnYG0HKyuOWN/uKA==} - dependencies: - '@types/react': 18.3.12 - dev: false - /@types/react@18.3.12: resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} dependencies: @@ -12484,16 +12478,16 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false - /linkify-it@2.2.0: - resolution: {integrity: sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==} + /linkify-it@3.0.3: + resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} dependencies: uc.micro: 1.0.6 dev: false - /linkify-it@3.0.3: - resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} + /linkify-it@6.1.0: + resolution: {integrity: sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==} dependencies: - uc.micro: 1.0.6 + uc.micro: 3.0.0 dev: false /load-module@4.2.1: @@ -14579,13 +14573,6 @@ packages: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} dev: false - /react-linkify@1.0.0-alpha: - resolution: {integrity: sha512-7gcIUvJkAXXttt1fmBK9cwn+1jTa4hbKLGCZ9J1U6EOkyb2/+LKL1Z28d9rtDLMnpvImlNlLPdTPooorl5cpmg==} - dependencies: - linkify-it: 2.2.0 - tlds: 1.260.0 - dev: false - /react-property@2.0.2: resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==} dev: false @@ -16245,11 +16232,6 @@ packages: engines: {node: '>=14.0.0'} dev: false - /tlds@1.260.0: - resolution: {integrity: sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ==} - hasBin: true - dev: false - /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: false @@ -16683,6 +16665,10 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: false + /uc.micro@3.0.0: + resolution: {integrity: sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==} + dev: false + /uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -17860,7 +17846,7 @@ packages: dev: false file:projects/acs-ui-javascript-loaders.tgz: - resolution: {integrity: sha512-8XT3x2MG2vyZiOrDCiiuW84duCLJHxZfncJ47PTA9L758s2bWmGCoIo5T+nMGOs+5YTRjmIn//UYN734UBl7SQ==, tarball: file:projects/acs-ui-javascript-loaders.tgz} + resolution: {integrity: sha512-aizHPttXewnvvGq3kGNR6aceHrD6nkZxA/88hyYgYIDHbtQKNuitY5IZG07/Un0R7PWECd+4ZgB6olWLzc3Zyw==, tarball: file:projects/acs-ui-javascript-loaders.tgz} name: '@rush-temp/acs-ui-javascript-loaders' version: 0.0.0 dependencies: @@ -17911,7 +17897,7 @@ packages: dev: false file:projects/calling-component-bindings.tgz: - resolution: {integrity: sha512-8R9SwbLNBKIv9fMuSfi0pbh8+888YlaSghawxoiLgim41zh/5QHQt0wrN3+3Dsg0OSjbR7P4KVchNhgcwo2eeA==, tarball: file:projects/calling-component-bindings.tgz} + resolution: {integrity: sha512-h4Iz2QT6+s2VmqqgeOdwtXQKs1LCVCzwBsHBG5/WX2rOLjo49dnAo/+4OsAj9Dad9BZ0Uu8eUH6aplE3BWTupA==, tarball: file:projects/calling-component-bindings.tgz} name: '@rush-temp/calling-component-bindings' version: 0.0.0 dependencies: @@ -17962,7 +17948,7 @@ packages: dev: false file:projects/calling-stateful-client.tgz: - resolution: {integrity: sha512-bTXWvbIg1O8AuUizIRhxjfKPevaHki2So9ljfCadC0Yxhucl3X8yeW3U6Jjezn5NiLRrzc3IKBOEN+T+Sn0GnQ==, tarball: file:projects/calling-stateful-client.tgz} + resolution: {integrity: sha512-sKZ771jT++PaafTZ897nGZrKreJ7uYgAj26g12MhTKn7qu1WaSO2P1zoGSGQUHdCveDEtnYkonI9+CBSluKvSQ==, tarball: file:projects/calling-stateful-client.tgz} name: '@rush-temp/calling-stateful-client' version: 0.0.0 dependencies: @@ -18015,7 +18001,7 @@ packages: dev: false file:projects/calling-stateful-samples.tgz: - resolution: {integrity: sha512-9K9ZPVIyobonLwPBknTfCstvImYyixnWqa7+w3oodprNh6bxp8mab53NBbPFmYrqiAzrvqOFI14Bc6wEavWjAw==, tarball: file:projects/calling-stateful-samples.tgz} + resolution: {integrity: sha512-kDxa+25et6Q4FXOWm7a+aK3FDT0H1qG+R+mCUazcmCcvV5a5fpi/RMvxLvtlkDivbtxZeRGEjHkL5yh6VLa2QA==, tarball: file:projects/calling-stateful-samples.tgz} name: '@rush-temp/calling-stateful-samples' version: 0.0.0 dependencies: @@ -18114,7 +18100,7 @@ packages: dev: false file:projects/calling.tgz: - resolution: {integrity: sha512-EalIr/2jI5646AQAHBJKz7Kau6Bg0EuESPLCLUpvZ837iNGXiAjz1lQv3z1ZHI02iGilxWMVYSzb3emKGOAiyQ==, tarball: file:projects/calling.tgz} + resolution: {integrity: sha512-LKFmOdpCi3PBWOQsvwxl4BrhDEGY6tqvUFU0z4s/ZBkTc4e7fZZHjsinADNRytcLnMsaU0fweCeqQThi2Yjbzg==, tarball: file:projects/calling.tgz} name: '@rush-temp/calling' version: 0.0.0 dependencies: @@ -18213,7 +18199,7 @@ packages: dev: false file:projects/callwithchat.tgz: - resolution: {integrity: sha512-vdSyJzOb2mq+OAfLQsS0LiOF73ol5S3qJrxOOnyIZmH6jpDYt9fm3W8l6U1sCdwjCZywGSmRquGAPZGs9nL2IA==, tarball: file:projects/callwithchat.tgz} + resolution: {integrity: sha512-T3LTvbAFePLFgvc3MLcUFvM7hJm2rr997C2AELQ75XZhee0aj7Vnc1b+sKx2/2XoJuIQca3nUkJwmn1YO6xzcQ==, tarball: file:projects/callwithchat.tgz} name: '@rush-temp/callwithchat' version: 0.0.0 dependencies: @@ -18310,7 +18296,7 @@ packages: dev: false file:projects/chat-component-bindings.tgz: - resolution: {integrity: sha512-kHxOXg7yZeIr5w4xSn8gfojOY3YWZQcJcI2sSOrXTqvjsv3r32wmXw0254EUw33HkqlB93u2rpWqwIWpQQz38g==, tarball: file:projects/chat-component-bindings.tgz} + resolution: {integrity: sha512-XoDBh4K0rzvrqI9lEJiifDL39VHVGwXuR7AxD3wehYyMNGlqMth1653jBDyzALFrbrMb2NbNSsSVKseUOLs2vw==, tarball: file:projects/chat-component-bindings.tgz} name: '@rush-temp/chat-component-bindings' version: 0.0.0 dependencies: @@ -18360,7 +18346,7 @@ packages: dev: false file:projects/chat-stateful-client.tgz: - resolution: {integrity: sha512-Xyb+Y8057+Cg1wnn+t9K6+9wCaXuVtFmBYnN9o8C7Db6Egg9nsVkcepVapWP3B0DaHXDtNVUr57f463x4ze8oA==, tarball: file:projects/chat-stateful-client.tgz} + resolution: {integrity: sha512-7UhnqPm7kXsQ4ie7px32lDPadhGCZTNjBzDLF3jZPhlxSC+s25/TOy0Cc7dTAA5ank2+isdWY2ar4i2L9NlEyA==, tarball: file:projects/chat-stateful-client.tgz} name: '@rush-temp/chat-stateful-client' version: 0.0.0 dependencies: @@ -18415,7 +18401,7 @@ packages: dev: false file:projects/chat.tgz: - resolution: {integrity: sha512-Ces3BWx360++IltwUE+VPRJYetrckbn7+A6KVSqwrERK6E/zYfoUSZ5BdNgI5c3goi1znD1P3CczyfIuwfcVrA==, tarball: file:projects/chat.tgz} + resolution: {integrity: sha512-HI89S/iIhuAXJe9P/WbajvMUv8H8hj91g1Ha72nSuQOeznmMp5rF65kGbc8RJH5XAEluuQDZ5jdKF3hvr+46wA==, tarball: file:projects/chat.tgz} name: '@rush-temp/chat' version: 0.0.0 dependencies: @@ -18437,7 +18423,6 @@ packages: '@types/json-stringify-safe': 5.0.3 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) axios: 1.12.2 @@ -18471,7 +18456,6 @@ packages: pretty-quick: 4.2.2(prettier@3.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-linkify: 1.0.0-alpha reselect: 4.1.8 rimraf: 2.7.1 shake.js: 1.2.2 @@ -18509,7 +18493,7 @@ packages: dev: false file:projects/check-treeshaking.tgz: - resolution: {integrity: sha512-2KJW7VH0NodlwaPJfmt2+kyIY1Dt40ZLsB8/RohwCRv/INF86525UzuFXaOOQVyJ56a6QXMeAXLiJWmEuaZsQg==, tarball: file:projects/check-treeshaking.tgz} + resolution: {integrity: sha512-tjgG09WNZuXl63VbuIs/TQZjqh1oeWzb+9lHTEpJfGSOvckcPVYKgIa3KXjrsm8nRj5SBiVWeQGNRwezypdXBg==, tarball: file:projects/check-treeshaking.tgz} name: '@rush-temp/check-treeshaking' version: 0.0.0 dependencies: @@ -18542,7 +18526,7 @@ packages: dev: false file:projects/check-typescript-regression.tgz: - resolution: {integrity: sha512-I4io8sSTnGCKXY/HNg5JrGSVJHQQUTTTqNhjxYtpPyfZD4fZY8L9KTL/nnvnInbqTnC1wJXTXVSNAKQ1tJ9Scg==, tarball: file:projects/check-typescript-regression.tgz} + resolution: {integrity: sha512-KePn4TBXuXEwA5skHEz+Wjy2cewptVO+/rlaXrZ5jalf/hSTdcedMVHNVaXrWqgfyfCEc1ZyYP86S1FZ0FvfqQ==, tarball: file:projects/check-typescript-regression.tgz} name: '@rush-temp/check-typescript-regression' version: 0.0.0 dependencies: @@ -18565,7 +18549,7 @@ packages: dev: false file:projects/communication-react.tgz: - resolution: {integrity: sha512-0EMxT6i7SsdTTMH9Z6mNQEPTYqiU7emvgCF810onS6XZSPyPzJ9edZ+rBb4qEGzPlYPMFAI6UgoCsVQTupp4rA==, tarball: file:projects/communication-react.tgz} + resolution: {integrity: sha512-ICSVwrqPRk5kSRnewcG9osrmAFGWierOXlyIzKsXZnsy7HySBNTh0e6NEsSX0MA8/kcxH6AXI/dZfUPshYF9gg==, tarball: file:projects/communication-react.tgz} name: '@rush-temp/communication-react' version: 0.0.0 dependencies: @@ -18601,7 +18585,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) @@ -18628,6 +18611,7 @@ packages: jest: 29.7.0(@types/node@22.18.1)(ts-node@10.9.2) jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 memoize-one: 5.2.1 nanoid: 3.3.8 node-forge: 1.3.3 @@ -18636,7 +18620,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha react-use-draggable-scroll: 0.4.7(react@18.3.1) regenerator-runtime: 0.14.1 renamer: 4.0.0 @@ -18676,7 +18659,7 @@ packages: dev: false file:projects/component-examples.tgz: - resolution: {integrity: sha512-UKYtS5OyOE74WRuMRt6bYsRAcmyCREdEb/XAoiWZbwQ7DDrT0nFbcUuzo9H2M5JdO3XB9TUYZoWh+KGBkAXx7w==, tarball: file:projects/component-examples.tgz} + resolution: {integrity: sha512-mRUuQg9KkuciRuYj0WW3X8pj83Dc0n+M2OXp6fOULXHsvL8cmOWiD0InOuw30Oa4t7qP16ryncY7pU5aYuqFvQ==, tarball: file:projects/component-examples.tgz} name: '@rush-temp/component-examples' version: 0.0.0 dependencies: @@ -18790,7 +18773,7 @@ packages: dev: false file:projects/fake-backends.tgz: - resolution: {integrity: sha512-JGeCgDSJLi9rAB2bClNDz18AoeHLUOOqC7lmJi+9Oq4h2TUbGY55PEe61AzyWUpPPaGp64tNNUpIBYG2gDET7g==, tarball: file:projects/fake-backends.tgz} + resolution: {integrity: sha512-eZsVxyKPNIJL6jPyZKIjqFP+et610B37elyv3B5Uy58qnRNTLDz7pjTKTDjiUSHgAmA4I4H+Ns07TsIX4OAqIQ==, tarball: file:projects/fake-backends.tgz} name: '@rush-temp/fake-backends' version: 0.0.0 dependencies: @@ -18850,7 +18833,7 @@ packages: dev: false file:projects/react-components.tgz: - resolution: {integrity: sha512-kucDeD+Mcx4TzFqUVztAoUsP/lieb5hv48OlOXOyEG7WQp/IulUZz/nFmcGt/pR80UFZVVZHssyMlNnO0a0RUw==, tarball: file:projects/react-components.tgz} + resolution: {integrity: sha512-Eb/X8b87M1fW3yGybDCLopEOLiUq5twVTzV0S18M8dZadyu7NcBA/f7hM1z8FI9v91B0NPGmGieDcJi6QfVmhw==, tarball: file:projects/react-components.tgz} name: '@rush-temp/react-components' version: 0.0.0 dependencies: @@ -18881,7 +18864,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) @@ -18916,6 +18898,7 @@ packages: jest-junit: 16.0.0 jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 nan: 2.23.0 node-forge: 1.3.3 playwright-core: 1.55.1 @@ -18924,7 +18907,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha react-use-draggable-scroll: 0.4.7(react@18.3.1) regenerator-runtime: 0.14.1 rimraf: 2.7.1 @@ -18974,7 +18956,7 @@ packages: dev: false file:projects/react-composites.tgz: - resolution: {integrity: sha512-GXi9xj/Vlvd/2kC0OGRHRJcnB3k6W1VNSTWOpJtMieBi1C7tqNI5Bca03ecFS7uuvNOAMXf06s3SNwcVXU7csw==, tarball: file:projects/react-composites.tgz} + resolution: {integrity: sha512-BiBn/S8/MOFmeCmeLD5mSmG/kHFH8pahml3pnyOj+2V/zTMAD2EnIWN2dfWl2jelANrHOJ2iw9gavJ1hmrNtcA==, tarball: file:projects/react-composites.tgz} name: '@rush-temp/react-composites' version: 0.0.0 dependencies: @@ -19009,7 +18991,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@types/yargs': 17.0.33 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) @@ -19049,6 +19030,7 @@ packages: jest-junit: 16.0.0 jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 memoize-one: 5.2.1 nan: 2.23.0 nanoid: 3.3.8 @@ -19058,7 +19040,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha regenerator-runtime: 0.14.1 reselect: 4.1.8 rimraf: 2.7.1 @@ -19123,7 +19104,7 @@ packages: dev: false file:projects/sample-static-html-composites.tgz: - resolution: {integrity: sha512-5qGepbkLc3BwRsnz99z3PxB/WuT9YFKDtaMnF6y4R37uHjqLzuoR5quYEyDYCBOfLgs3gt+ySgCw+IIHtbtm1Q==, tarball: file:projects/sample-static-html-composites.tgz} + resolution: {integrity: sha512-MjbBFzbKOCfXEpba3SUd9yu3MuhrGNOUKAkht8/Ryq3kDONSe8MbTI40eg3pXj3Sokze/bFTVaS4eYH9c5Wlow==, tarball: file:projects/sample-static-html-composites.tgz} name: '@rush-temp/sample-static-html-composites' version: 0.0.0 dependencies: @@ -19269,7 +19250,7 @@ packages: dev: false file:projects/storybook8.tgz: - resolution: {integrity: sha512-1LhibQPVOuOuDl640MlqSFg317k5hK0FtUdFTmEoxl7JYiuuJPOzh6XWT2mNkqdpuWX82+H6yVfrfzeM2XUVRw==, tarball: file:projects/storybook8.tgz} + resolution: {integrity: sha512-Ls/IPDHA+7eGB0b44fO8HZNOg19KPmJsIhcNXFNPJtLRIOF6i+CfTD2YgNG4JZbu/WWsJ5QglpR45/kMBJREdQ==, tarball: file:projects/storybook8.tgz} name: '@rush-temp/storybook8' version: 0.0.0 dependencies: @@ -19315,7 +19296,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) diff --git a/common/config/rush/variants/stable/pnpm-lock.yaml b/common/config/rush/variants/stable/pnpm-lock.yaml index 1fbc1c7f86d..15f1ad09a52 100644 --- a/common/config/rush/variants/stable/pnpm-lock.yaml +++ b/common/config/rush/variants/stable/pnpm-lock.yaml @@ -6308,12 +6308,6 @@ packages: '@types/react': 18.3.12 dev: false - /@types/react-linkify@1.0.4: - resolution: {integrity: sha512-NOMw4X3kjvjY0lT5kXQdxZCXpPNi2hOuuqG+Kz+5EOQpi9rDUJJDitdE1j2JRNmrTnNIjrLnYG0HKyuOWN/uKA==} - dependencies: - '@types/react': 18.3.12 - dev: false - /@types/react@18.3.12: resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} dependencies: @@ -12467,16 +12461,16 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false - /linkify-it@2.2.0: - resolution: {integrity: sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==} + /linkify-it@3.0.3: + resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} dependencies: uc.micro: 1.0.6 dev: false - /linkify-it@3.0.3: - resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} + /linkify-it@6.1.0: + resolution: {integrity: sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==} dependencies: - uc.micro: 1.0.6 + uc.micro: 3.0.0 dev: false /load-module@4.2.1: @@ -14562,13 +14556,6 @@ packages: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} dev: false - /react-linkify@1.0.0-alpha: - resolution: {integrity: sha512-7gcIUvJkAXXttt1fmBK9cwn+1jTa4hbKLGCZ9J1U6EOkyb2/+LKL1Z28d9rtDLMnpvImlNlLPdTPooorl5cpmg==} - dependencies: - linkify-it: 2.2.0 - tlds: 1.260.0 - dev: false - /react-property@2.0.2: resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==} dev: false @@ -16228,11 +16215,6 @@ packages: engines: {node: '>=14.0.0'} dev: false - /tlds@1.260.0: - resolution: {integrity: sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ==} - hasBin: true - dev: false - /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: false @@ -16666,6 +16648,10 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: false + /uc.micro@3.0.0: + resolution: {integrity: sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==} + dev: false + /uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -17843,7 +17829,7 @@ packages: dev: false file:projects/acs-ui-javascript-loaders.tgz: - resolution: {integrity: sha512-8XT3x2MG2vyZiOrDCiiuW84duCLJHxZfncJ47PTA9L758s2bWmGCoIo5T+nMGOs+5YTRjmIn//UYN734UBl7SQ==, tarball: file:projects/acs-ui-javascript-loaders.tgz} + resolution: {integrity: sha512-aizHPttXewnvvGq3kGNR6aceHrD6nkZxA/88hyYgYIDHbtQKNuitY5IZG07/Un0R7PWECd+4ZgB6olWLzc3Zyw==, tarball: file:projects/acs-ui-javascript-loaders.tgz} name: '@rush-temp/acs-ui-javascript-loaders' version: 0.0.0 dependencies: @@ -17894,7 +17880,7 @@ packages: dev: false file:projects/calling-component-bindings.tgz: - resolution: {integrity: sha512-8R9SwbLNBKIv9fMuSfi0pbh8+888YlaSghawxoiLgim41zh/5QHQt0wrN3+3Dsg0OSjbR7P4KVchNhgcwo2eeA==, tarball: file:projects/calling-component-bindings.tgz} + resolution: {integrity: sha512-h4Iz2QT6+s2VmqqgeOdwtXQKs1LCVCzwBsHBG5/WX2rOLjo49dnAo/+4OsAj9Dad9BZ0Uu8eUH6aplE3BWTupA==, tarball: file:projects/calling-component-bindings.tgz} name: '@rush-temp/calling-component-bindings' version: 0.0.0 dependencies: @@ -17945,7 +17931,7 @@ packages: dev: false file:projects/calling-stateful-client.tgz: - resolution: {integrity: sha512-bTXWvbIg1O8AuUizIRhxjfKPevaHki2So9ljfCadC0Yxhucl3X8yeW3U6Jjezn5NiLRrzc3IKBOEN+T+Sn0GnQ==, tarball: file:projects/calling-stateful-client.tgz} + resolution: {integrity: sha512-sKZ771jT++PaafTZ897nGZrKreJ7uYgAj26g12MhTKn7qu1WaSO2P1zoGSGQUHdCveDEtnYkonI9+CBSluKvSQ==, tarball: file:projects/calling-stateful-client.tgz} name: '@rush-temp/calling-stateful-client' version: 0.0.0 dependencies: @@ -17998,7 +17984,7 @@ packages: dev: false file:projects/calling-stateful-samples.tgz: - resolution: {integrity: sha512-9K9ZPVIyobonLwPBknTfCstvImYyixnWqa7+w3oodprNh6bxp8mab53NBbPFmYrqiAzrvqOFI14Bc6wEavWjAw==, tarball: file:projects/calling-stateful-samples.tgz} + resolution: {integrity: sha512-kDxa+25et6Q4FXOWm7a+aK3FDT0H1qG+R+mCUazcmCcvV5a5fpi/RMvxLvtlkDivbtxZeRGEjHkL5yh6VLa2QA==, tarball: file:projects/calling-stateful-samples.tgz} name: '@rush-temp/calling-stateful-samples' version: 0.0.0 dependencies: @@ -18097,7 +18083,7 @@ packages: dev: false file:projects/calling.tgz: - resolution: {integrity: sha512-EalIr/2jI5646AQAHBJKz7Kau6Bg0EuESPLCLUpvZ837iNGXiAjz1lQv3z1ZHI02iGilxWMVYSzb3emKGOAiyQ==, tarball: file:projects/calling.tgz} + resolution: {integrity: sha512-LKFmOdpCi3PBWOQsvwxl4BrhDEGY6tqvUFU0z4s/ZBkTc4e7fZZHjsinADNRytcLnMsaU0fweCeqQThi2Yjbzg==, tarball: file:projects/calling.tgz} name: '@rush-temp/calling' version: 0.0.0 dependencies: @@ -18196,7 +18182,7 @@ packages: dev: false file:projects/callwithchat.tgz: - resolution: {integrity: sha512-vdSyJzOb2mq+OAfLQsS0LiOF73ol5S3qJrxOOnyIZmH6jpDYt9fm3W8l6U1sCdwjCZywGSmRquGAPZGs9nL2IA==, tarball: file:projects/callwithchat.tgz} + resolution: {integrity: sha512-T3LTvbAFePLFgvc3MLcUFvM7hJm2rr997C2AELQ75XZhee0aj7Vnc1b+sKx2/2XoJuIQca3nUkJwmn1YO6xzcQ==, tarball: file:projects/callwithchat.tgz} name: '@rush-temp/callwithchat' version: 0.0.0 dependencies: @@ -18293,7 +18279,7 @@ packages: dev: false file:projects/chat-component-bindings.tgz: - resolution: {integrity: sha512-kHxOXg7yZeIr5w4xSn8gfojOY3YWZQcJcI2sSOrXTqvjsv3r32wmXw0254EUw33HkqlB93u2rpWqwIWpQQz38g==, tarball: file:projects/chat-component-bindings.tgz} + resolution: {integrity: sha512-XoDBh4K0rzvrqI9lEJiifDL39VHVGwXuR7AxD3wehYyMNGlqMth1653jBDyzALFrbrMb2NbNSsSVKseUOLs2vw==, tarball: file:projects/chat-component-bindings.tgz} name: '@rush-temp/chat-component-bindings' version: 0.0.0 dependencies: @@ -18343,7 +18329,7 @@ packages: dev: false file:projects/chat-stateful-client.tgz: - resolution: {integrity: sha512-Xyb+Y8057+Cg1wnn+t9K6+9wCaXuVtFmBYnN9o8C7Db6Egg9nsVkcepVapWP3B0DaHXDtNVUr57f463x4ze8oA==, tarball: file:projects/chat-stateful-client.tgz} + resolution: {integrity: sha512-7UhnqPm7kXsQ4ie7px32lDPadhGCZTNjBzDLF3jZPhlxSC+s25/TOy0Cc7dTAA5ank2+isdWY2ar4i2L9NlEyA==, tarball: file:projects/chat-stateful-client.tgz} name: '@rush-temp/chat-stateful-client' version: 0.0.0 dependencies: @@ -18398,7 +18384,7 @@ packages: dev: false file:projects/chat.tgz: - resolution: {integrity: sha512-Ces3BWx360++IltwUE+VPRJYetrckbn7+A6KVSqwrERK6E/zYfoUSZ5BdNgI5c3goi1znD1P3CczyfIuwfcVrA==, tarball: file:projects/chat.tgz} + resolution: {integrity: sha512-HI89S/iIhuAXJe9P/WbajvMUv8H8hj91g1Ha72nSuQOeznmMp5rF65kGbc8RJH5XAEluuQDZ5jdKF3hvr+46wA==, tarball: file:projects/chat.tgz} name: '@rush-temp/chat' version: 0.0.0 dependencies: @@ -18420,7 +18406,6 @@ packages: '@types/json-stringify-safe': 5.0.3 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) axios: 1.12.2 @@ -18454,7 +18439,6 @@ packages: pretty-quick: 4.2.2(prettier@3.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-linkify: 1.0.0-alpha reselect: 4.1.8 rimraf: 2.7.1 shake.js: 1.2.2 @@ -18492,7 +18476,7 @@ packages: dev: false file:projects/check-treeshaking.tgz: - resolution: {integrity: sha512-2KJW7VH0NodlwaPJfmt2+kyIY1Dt40ZLsB8/RohwCRv/INF86525UzuFXaOOQVyJ56a6QXMeAXLiJWmEuaZsQg==, tarball: file:projects/check-treeshaking.tgz} + resolution: {integrity: sha512-tjgG09WNZuXl63VbuIs/TQZjqh1oeWzb+9lHTEpJfGSOvckcPVYKgIa3KXjrsm8nRj5SBiVWeQGNRwezypdXBg==, tarball: file:projects/check-treeshaking.tgz} name: '@rush-temp/check-treeshaking' version: 0.0.0 dependencies: @@ -18525,7 +18509,7 @@ packages: dev: false file:projects/check-typescript-regression.tgz: - resolution: {integrity: sha512-I4io8sSTnGCKXY/HNg5JrGSVJHQQUTTTqNhjxYtpPyfZD4fZY8L9KTL/nnvnInbqTnC1wJXTXVSNAKQ1tJ9Scg==, tarball: file:projects/check-typescript-regression.tgz} + resolution: {integrity: sha512-KePn4TBXuXEwA5skHEz+Wjy2cewptVO+/rlaXrZ5jalf/hSTdcedMVHNVaXrWqgfyfCEc1ZyYP86S1FZ0FvfqQ==, tarball: file:projects/check-typescript-regression.tgz} name: '@rush-temp/check-typescript-regression' version: 0.0.0 dependencies: @@ -18548,7 +18532,7 @@ packages: dev: false file:projects/communication-react.tgz: - resolution: {integrity: sha512-0EMxT6i7SsdTTMH9Z6mNQEPTYqiU7emvgCF810onS6XZSPyPzJ9edZ+rBb4qEGzPlYPMFAI6UgoCsVQTupp4rA==, tarball: file:projects/communication-react.tgz} + resolution: {integrity: sha512-ICSVwrqPRk5kSRnewcG9osrmAFGWierOXlyIzKsXZnsy7HySBNTh0e6NEsSX0MA8/kcxH6AXI/dZfUPshYF9gg==, tarball: file:projects/communication-react.tgz} name: '@rush-temp/communication-react' version: 0.0.0 dependencies: @@ -18584,7 +18568,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) @@ -18611,6 +18594,7 @@ packages: jest: 29.7.0(@types/node@22.18.1)(ts-node@10.9.2) jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 memoize-one: 5.2.1 nanoid: 3.3.8 node-forge: 1.3.3 @@ -18619,7 +18603,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha react-use-draggable-scroll: 0.4.7(react@18.3.1) regenerator-runtime: 0.14.1 renamer: 4.0.0 @@ -18659,7 +18642,7 @@ packages: dev: false file:projects/component-examples.tgz: - resolution: {integrity: sha512-UKYtS5OyOE74WRuMRt6bYsRAcmyCREdEb/XAoiWZbwQ7DDrT0nFbcUuzo9H2M5JdO3XB9TUYZoWh+KGBkAXx7w==, tarball: file:projects/component-examples.tgz} + resolution: {integrity: sha512-mRUuQg9KkuciRuYj0WW3X8pj83Dc0n+M2OXp6fOULXHsvL8cmOWiD0InOuw30Oa4t7qP16ryncY7pU5aYuqFvQ==, tarball: file:projects/component-examples.tgz} name: '@rush-temp/component-examples' version: 0.0.0 dependencies: @@ -18773,7 +18756,7 @@ packages: dev: false file:projects/fake-backends.tgz: - resolution: {integrity: sha512-JGeCgDSJLi9rAB2bClNDz18AoeHLUOOqC7lmJi+9Oq4h2TUbGY55PEe61AzyWUpPPaGp64tNNUpIBYG2gDET7g==, tarball: file:projects/fake-backends.tgz} + resolution: {integrity: sha512-eZsVxyKPNIJL6jPyZKIjqFP+et610B37elyv3B5Uy58qnRNTLDz7pjTKTDjiUSHgAmA4I4H+Ns07TsIX4OAqIQ==, tarball: file:projects/fake-backends.tgz} name: '@rush-temp/fake-backends' version: 0.0.0 dependencies: @@ -18833,7 +18816,7 @@ packages: dev: false file:projects/react-components.tgz: - resolution: {integrity: sha512-kucDeD+Mcx4TzFqUVztAoUsP/lieb5hv48OlOXOyEG7WQp/IulUZz/nFmcGt/pR80UFZVVZHssyMlNnO0a0RUw==, tarball: file:projects/react-components.tgz} + resolution: {integrity: sha512-Eb/X8b87M1fW3yGybDCLopEOLiUq5twVTzV0S18M8dZadyu7NcBA/f7hM1z8FI9v91B0NPGmGieDcJi6QfVmhw==, tarball: file:projects/react-components.tgz} name: '@rush-temp/react-components' version: 0.0.0 dependencies: @@ -18864,7 +18847,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) @@ -18899,6 +18881,7 @@ packages: jest-junit: 16.0.0 jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 nan: 2.23.0 node-forge: 1.3.3 playwright-core: 1.55.1 @@ -18907,7 +18890,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha react-use-draggable-scroll: 0.4.7(react@18.3.1) regenerator-runtime: 0.14.1 rimraf: 2.7.1 @@ -18957,7 +18939,7 @@ packages: dev: false file:projects/react-composites.tgz: - resolution: {integrity: sha512-GXi9xj/Vlvd/2kC0OGRHRJcnB3k6W1VNSTWOpJtMieBi1C7tqNI5Bca03ecFS7uuvNOAMXf06s3SNwcVXU7csw==, tarball: file:projects/react-composites.tgz} + resolution: {integrity: sha512-BiBn/S8/MOFmeCmeLD5mSmG/kHFH8pahml3pnyOj+2V/zTMAD2EnIWN2dfWl2jelANrHOJ2iw9gavJ1hmrNtcA==, tarball: file:projects/react-composites.tgz} name: '@rush-temp/react-composites' version: 0.0.0 dependencies: @@ -18992,7 +18974,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@types/yargs': 17.0.33 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) @@ -19032,6 +19013,7 @@ packages: jest-junit: 16.0.0 jiti: 2.4.2 json-stringify-safe: 5.0.1 + linkify-it: 6.1.0 memoize-one: 5.2.1 nan: 2.23.0 nanoid: 3.3.8 @@ -19041,7 +19023,6 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-linkify: 1.0.0-alpha regenerator-runtime: 0.14.1 reselect: 4.1.8 rimraf: 2.7.1 @@ -19106,7 +19087,7 @@ packages: dev: false file:projects/sample-static-html-composites.tgz: - resolution: {integrity: sha512-5qGepbkLc3BwRsnz99z3PxB/WuT9YFKDtaMnF6y4R37uHjqLzuoR5quYEyDYCBOfLgs3gt+ySgCw+IIHtbtm1Q==, tarball: file:projects/sample-static-html-composites.tgz} + resolution: {integrity: sha512-MjbBFzbKOCfXEpba3SUd9yu3MuhrGNOUKAkht8/Ryq3kDONSe8MbTI40eg3pXj3Sokze/bFTVaS4eYH9c5Wlow==, tarball: file:projects/sample-static-html-composites.tgz} name: '@rush-temp/sample-static-html-composites' version: 0.0.0 dependencies: @@ -19252,7 +19233,7 @@ packages: dev: false file:projects/storybook8.tgz: - resolution: {integrity: sha512-1LhibQPVOuOuDl640MlqSFg317k5hK0FtUdFTmEoxl7JYiuuJPOzh6XWT2mNkqdpuWX82+H6yVfrfzeM2XUVRw==, tarball: file:projects/storybook8.tgz} + resolution: {integrity: sha512-Ls/IPDHA+7eGB0b44fO8HZNOg19KPmJsIhcNXFNPJtLRIOF6i+CfTD2YgNG4JZbu/WWsJ5QglpR45/kMBJREdQ==, tarball: file:projects/storybook8.tgz} name: '@rush-temp/storybook8' version: 0.0.0 dependencies: @@ -19298,7 +19279,6 @@ packages: '@types/node': 22.18.1 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@types/react-linkify': 1.0.4 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0)(eslint@9.35.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.4.5) diff --git a/packages/communication-react/package.json b/packages/communication-react/package.json index 44771edecdc..c25e80c02c2 100644 --- a/packages/communication-react/package.json +++ b/packages/communication-react/package.json @@ -42,7 +42,7 @@ "immer": "10.1.1", "memoize-one": "^5.2.1", "nanoid": "3.3.8", - "react-linkify": "^1.0.0-alpha", + "linkify-it": "^6.1.0", "react-use-draggable-scroll": "^0.4.7", "reselect": "^4.0.0", "roosterjs-content-model-api": "^9.27.0", @@ -134,7 +134,6 @@ "@types/json-stringify-safe": "^5.0.3", "@types/node": "^22.15.18", "@types/react-dom": "18.3.1", - "@types/react-linkify": "^1.0.4", "@types/react": "18.3.12", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^8.34.0", diff --git a/packages/react-components/package.json b/packages/react-components/package.json index f16031f10f6..46d3655f338 100644 --- a/packages/react-components/package.json +++ b/packages/react-components/package.json @@ -49,7 +49,7 @@ "copy-to-clipboard": "^3.3.1", "dompurify": "^3.2.5", "html-react-parser": "^5.2.3", - "react-linkify": "^1.0.0-alpha", + "linkify-it": "^6.1.0", "react-use-draggable-scroll": "^0.4.7", "roosterjs-content-model-api": "^9.27.0", "roosterjs-content-model-core": "^9.27.0", @@ -82,7 +82,6 @@ "@types/json-stringify-safe": "^5.0.3", "@types/node": "^22.15.18", "@types/react-dom": "18.3.1", - "@types/react-linkify": "^1.0.4", "@types/react": "18.3.12", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^8.34.0", diff --git a/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx b/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx new file mode 100644 index 00000000000..1dd20c67802 --- /dev/null +++ b/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import React from 'react'; +import { screen } from '@testing-library/react'; +import { COMPONENT_LOCALE_EN_US } from '../../localization/locales'; +import { renderWithLiveAnnouncer } from '../utils/testUtils'; +import { ChatMessageContent } from './ChatMessageContent'; + +describe('ChatMessageContent', () => { + test('renders links in plain-text messages', () => { + renderWithLiveAnnouncer( + + ); + + expect(screen.getByRole('text').textContent).toBe( + 'Visit https://contoso.com or email user@contoso.com for help.' + ); + expect(screen.getByRole('link', { name: 'https://contoso.com' }).getAttribute('href')).toBe( + 'https://contoso.com' + ); + expect(screen.getByRole('link', { name: 'user@contoso.com' }).getAttribute('href')).toBe( + 'mailto:user@contoso.com' + ); + screen.getAllByRole('link').forEach((link) => expect(link.getAttribute('target')).toBe('_blank')); + }); +}); \ No newline at end of file diff --git a/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx b/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx index a7169932289..d2bce4f8d26 100644 --- a/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx +++ b/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { AttachmentMetadata, _formatString } from '@internal/acs-ui-common'; import parse, { HTMLReactParserOptions, Element as DOMElement } from 'html-react-parser'; import { attributesToProps } from 'html-react-parser'; -import Linkify from 'react-linkify'; +import { LinkifyIt } from 'linkify-it'; import { ChatMessage } from '../../types/ChatMessage'; /* @conditional-compile-remove(data-loss-prevention) */ import { BlockedMessage } from '../../types/ChatMessage'; @@ -25,6 +25,8 @@ import { _AttachmentDownloadCardsStrings } from '../Attachment/AttachmentDownloa import { dataLossIconStyle } from '../styles/MessageThread.styles'; import { messageTextContentStyles } from '../styles/MessageThread.styles'; +const linkify = new LinkifyIt(); + type ChatMessageContentProps = { message: ChatMessage; strings: MessageThreadStrings; @@ -116,23 +118,32 @@ const MessageContentAsText = (props: ChatMessageContentProps): JSX.Element => { liveMessage={generateLiveMessage(props)} ariaLabel={messageContentAriaText(props)} className={messageTextContentStyles} - content={ - { - return ( - - {decoratedText} - - ); - }} - > - {props.message.content} - - } + content={<>{linkifyMessageContent(props.message.content ?? '')}} /> ); }; +const linkifyMessageContent = (content: string): React.ReactNode[] => { + const matches = linkify.match(content); + if (!matches) { + return [content]; + } + + const contentParts: React.ReactNode[] = []; + let previousMatchEnd = 0; + matches.forEach((match) => { + contentParts.push(content.slice(previousMatchEnd, match.index)); + contentParts.push( + + {match.text} + + ); + previousMatchEnd = match.lastIndex; + }); + contentParts.push(content.slice(previousMatchEnd)); + return contentParts; +}; + /* @conditional-compile-remove(data-loss-prevention) */ /** * @private diff --git a/packages/react-composites/package.json b/packages/react-composites/package.json index e0c24b9f1e8..c0274e76b82 100644 --- a/packages/react-composites/package.json +++ b/packages/react-composites/package.json @@ -67,7 +67,7 @@ "events": "^3.3.0", "immer": "10.1.1", "memoize-one": "^5.2.1", - "react-linkify": "^1.0.0-alpha", + "linkify-it": "^6.1.0", "reselect": "^4.0.0", "uuid": "^9.0.0", "nanoid": "3.3.8" @@ -99,7 +99,6 @@ "@types/json-stringify-safe": "^5.0.3", "@types/node": "^22.15.18", "@types/react-dom": "18.3.1", - "@types/react-linkify": "^1.0.4", "@types/react": "18.3.12", "@types/uuid": "^9.0.8", "@types/yargs": "^17.0.29", diff --git a/packages/storybook8/package.json b/packages/storybook8/package.json index 0154a08c147..3523f85caa5 100644 --- a/packages/storybook8/package.json +++ b/packages/storybook8/package.json @@ -71,7 +71,6 @@ "@types/json-stringify-safe": "^5.0.3", "@types/node": "^22.15.18", "@types/react-dom": "18.3.1", - "@types/react-linkify": "^1.0.4", "@types/react": "18.3.12", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^8.34.0", diff --git a/samples/Chat/package.json b/samples/Chat/package.json index bf76a2d1578..906c4fb390c 100644 --- a/samples/Chat/package.json +++ b/samples/Chat/package.json @@ -45,12 +45,10 @@ "@fluentui/react": "^8.123.0", "@fluentui/react-file-type-icons": "8.13.2", "@fluentui/react-icons": "^2.0.302", - "@types/react-linkify": "^1.0.4", "json-stringify-safe": "^5.0.1", "mobile-detect": "^1.4.5", "react": "18.3.1", "react-dom": "18.3.1", - "react-linkify": "^1.0.0-alpha", "reselect": "^4.0.0", "shake.js": "1.2.2", "axios": "^1.12.2", From ea23d2b4c305137af693dcd66041bf5b89da90c5 Mon Sep 17 00:00:00 2001 From: mgamis-msft Date: Thu, 17 Sep 2026 03:04:04 -0700 Subject: [PATCH 2/3] Change files --- ...ation-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json | 9 +++++++++ ...ation-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 change-beta/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json create mode 100644 change/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json diff --git a/change-beta/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json b/change-beta/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json new file mode 100644 index 00000000000..a89a5a083f2 --- /dev/null +++ b/change-beta/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json @@ -0,0 +1,9 @@ +{ + "type": "patch", + "area": "fix", + "workstream": "communication-react dependencies", + "comment": "Fix linkify-it CVE in communication-react dependencies", + "packageName": "@azure/communication-react", + "email": "miguelgamis@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json b/change/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json new file mode 100644 index 00000000000..a89a5a083f2 --- /dev/null +++ b/change/@azure-communication-react-eef24f76-0530-41b7-b6fd-90ceefe5e3c2.json @@ -0,0 +1,9 @@ +{ + "type": "patch", + "area": "fix", + "workstream": "communication-react dependencies", + "comment": "Fix linkify-it CVE in communication-react dependencies", + "packageName": "@azure/communication-react", + "email": "miguelgamis@microsoft.com", + "dependentChangeType": "patch" +} From 7e7b4afc2ced72394e1525190c1e5f866fa06cc1 Mon Sep 17 00:00:00 2001 From: mgamis-msft Date: Thu, 24 Sep 2026 12:40:40 -0700 Subject: [PATCH 3/3] Set fuzzyLink: true to preserve previous `react-linkify` behavior because `linkify-it@6.1.0` defaults to false. --- .../components/ChatMessage/ChatMessageContent.test.tsx | 8 ++++++-- .../src/components/ChatMessage/ChatMessageContent.tsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx b/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx index 1dd20c67802..d3efce9333b 100644 --- a/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx +++ b/packages/react-components/src/components/ChatMessage/ChatMessageContent.test.tsx @@ -15,7 +15,7 @@ describe('ChatMessageContent', () => { messageId: 'message-id', messageType: 'chat', contentType: 'text', - content: 'Visit https://contoso.com or email user@contoso.com for help.', + content: 'Visit https://contoso.com, www.fabrikam.com, or fabrikam.com and email user@contoso.com for help.', createdOn: new Date() }} strings={COMPONENT_LOCALE_EN_US.strings.messageThread} @@ -23,7 +23,7 @@ describe('ChatMessageContent', () => { ); expect(screen.getByRole('text').textContent).toBe( - 'Visit https://contoso.com or email user@contoso.com for help.' + 'Visit https://contoso.com, www.fabrikam.com, or fabrikam.com and email user@contoso.com for help.' ); expect(screen.getByRole('link', { name: 'https://contoso.com' }).getAttribute('href')).toBe( 'https://contoso.com' @@ -31,6 +31,10 @@ describe('ChatMessageContent', () => { expect(screen.getByRole('link', { name: 'user@contoso.com' }).getAttribute('href')).toBe( 'mailto:user@contoso.com' ); + expect(screen.getByRole('link', { name: 'www.fabrikam.com' }).getAttribute('href')).toBe( + 'http://www.fabrikam.com' + ); + expect(screen.getByRole('link', { name: 'fabrikam.com' }).getAttribute('href')).toBe('http://fabrikam.com'); screen.getAllByRole('link').forEach((link) => expect(link.getAttribute('target')).toBe('_blank')); }); }); \ No newline at end of file diff --git a/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx b/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx index d2bce4f8d26..3e306f7e440 100644 --- a/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx +++ b/packages/react-components/src/components/ChatMessage/ChatMessageContent.tsx @@ -25,7 +25,7 @@ import { _AttachmentDownloadCardsStrings } from '../Attachment/AttachmentDownloa import { dataLossIconStyle } from '../styles/MessageThread.styles'; import { messageTextContentStyles } from '../styles/MessageThread.styles'; -const linkify = new LinkifyIt(); +const linkify = new LinkifyIt({ fuzzyLink: true }); type ChatMessageContentProps = { message: ChatMessage;