Преглед на файлове

fix(chat-URLs): Use punycode only on host name.

This is workaround for PunycodeJS which truncates parts of the URL when
it contains '@'.
factor2
Hristo Terezov преди 2 години
родител
ревизия
159dd13c2d

+ 7
- 7
package-lock.json Целия файл

@@ -67,7 +67,7 @@
67 67
         "null-loader": "4.0.1",
68 68
         "optional-require": "1.0.3",
69 69
         "promise.allsettled": "1.0.4",
70
-        "punycode": "2.1.1",
70
+        "punycode": "2.3.0",
71 71
         "react": "18.2.0",
72 72
         "react-dom": "18.2.0",
73 73
         "react-emoji-render": "1.2.4",
@@ -15399,9 +15399,9 @@
15399 15399
       }
15400 15400
     },
15401 15401
     "node_modules/punycode": {
15402
-      "version": "2.1.1",
15403
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
15404
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
15402
+      "version": "2.3.0",
15403
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
15404
+      "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
15405 15405
       "engines": {
15406 15406
         "node": ">=6"
15407 15407
       }
@@ -31282,9 +31282,9 @@
31282 31282
       }
31283 31283
     },
31284 31284
     "punycode": {
31285
-      "version": "2.1.1",
31286
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
31287
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
31285
+      "version": "2.3.0",
31286
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
31287
+      "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
31288 31288
     },
31289 31289
     "qs": {
31290 31290
       "version": "6.9.7",

+ 1
- 1
package.json Целия файл

@@ -72,7 +72,7 @@
72 72
     "null-loader": "4.0.1",
73 73
     "optional-require": "1.0.3",
74 74
     "promise.allsettled": "1.0.4",
75
-    "punycode": "2.1.1",
75
+    "punycode": "2.3.0",
76 76
     "react": "18.2.0",
77 77
     "react-dom": "18.2.0",
78 78
     "react-emoji-render": "1.2.4",

+ 2
- 2
react/features/base/react/components/native/Linkify.tsx Целия файл

@@ -1,9 +1,9 @@
1
-import punycode from 'punycode';
2 1
 import React, { Component } from 'react';
3 2
 import ReactLinkify from 'react-linkify';
4 3
 import { Text } from 'react-native';
5 4
 
6 5
 import { StyleType } from '../../../styles/functions.any';
6
+import { formatURLText } from '../../functions';
7 7
 
8 8
 import Link from './Link';
9 9
 
@@ -72,7 +72,7 @@ export default class Linkify extends Component<IProps> {
72 72
                 key = { key }
73 73
                 style = { this.props.linkStyle }
74 74
                 url = { decoratedHref }>
75
-                { punycode.toASCII(decoratedText) }
75
+                { formatURLText(decoratedText) }
76 76
             </Link>
77 77
         );
78 78
     }

+ 3
- 2
react/features/base/react/components/web/Linkify.tsx Целия файл

@@ -1,7 +1,8 @@
1
-import punycode from 'punycode';
2 1
 import React, { Component, ReactNode } from 'react';
3 2
 import ReactLinkify from 'react-linkify';
4 3
 
4
+import { formatURLText } from '../../functions';
5
+
5 6
 interface IProps {
6 7
 
7 8
     /**
@@ -43,7 +44,7 @@ export default class Linkify extends Component<IProps> {
43 44
                 key = { key }
44 45
                 rel = 'noopener noreferrer'
45 46
                 target = '_blank'>
46
-                { punycode.toASCII(decoratedText) }
47
+                { formatURLText(decoratedText) }
47 48
             </a>
48 49
         );
49 50
     }

+ 40
- 0
react/features/base/react/functions.ts Целия файл

@@ -1,3 +1,5 @@
1
+import punycode from 'punycode';
2
+
1 3
 /**
2 4
  * Returns the field value in a platform generic way.
3 5
  *
@@ -7,3 +9,41 @@
7 9
 export function getFieldValue(fieldParameter: { target: { value: string; }; } | string) {
8 10
     return typeof fieldParameter === 'string' ? fieldParameter : fieldParameter?.target?.value;
9 11
 }
12
+
13
+/**
14
+ * Formats the URL text for react-linkify.
15
+ *
16
+ * @param {string} text - The URL text.
17
+ * @returns {string} - The formatted text.
18
+ */
19
+export function formatURLText(text = '') {
20
+    let result;
21
+
22
+    // In order to prevent homograph attacks we need to use punycode. Reference
23
+    // https://github.com/tasti/react-linkify/issues/84. In the same time it seems PunycodeJS will treat the URL
24
+    // as an email when there is '@' and will erase parts of it. This is problematic if there is a URL like
25
+    // https://example.com/@test@@@123/test@test, punycode will truncate this to https://example.com/@test which
26
+    // is security issue because parts of the URL are actually missing from the text that we display. That's why
27
+    // we use punycode on valid URLs(that don't have '@' as part of the host) only for the host part of the URL.
28
+    try {
29
+        const url = new URL(text);
30
+        const { host } = url;
31
+
32
+        if (host) {
33
+            url.host = punycode.toASCII(host);
34
+            result = url.toString();
35
+        }
36
+    } catch (e) {
37
+        // Not a valid URL
38
+    }
39
+
40
+    if (!result) {
41
+        // This will be the case for invalid URLs or URLs without a host (emails for example). In this case beacuse
42
+        // of the issue with PunycodeJS that truncates parts of the text when there is '@' we split the text by '@'
43
+        // and use punycode for every separate part to prevent homograph attacks.
44
+        result = text.split('@').map(punycode.toASCII)
45
+            .join('@');
46
+    }
47
+
48
+    return result;
49
+}

Loading…
Отказ
Запис