Page MenuHomePhabricator

D9883.diff
No OneTemporary

D9883.diff

diff --git a/lib/package.json b/lib/package.json
--- a/lib/package.json
+++ b/lib/package.json
@@ -42,6 +42,7 @@
"fast-json-stable-stringify": "^2.0.0",
"file-type": "^12.3.0",
"focus-trap-react": "^10.1.4",
+ "idna-uts46-hx": "^2.3.1",
"invariant": "^2.2.4",
"just-clone": "^3.2.1",
"lodash": "^4.17.21",
diff --git a/lib/shared/markdown.js b/lib/shared/markdown.js
--- a/lib/shared/markdown.js
+++ b/lib/shared/markdown.js
@@ -348,6 +348,8 @@
);
}
+const ensRegex: RegExp = /^.{3,}\.eth$/;
+
export {
paragraphRegex,
paragraphStripTrailingNewlineRegex,
@@ -373,4 +375,5 @@
stripSpoilersFromNotifications,
stripSpoilersFromMarkdownAST,
parseChatMention,
+ ensRegex,
};
diff --git a/lib/utils/ens-helpers.js b/lib/utils/ens-helpers.js
--- a/lib/utils/ens-helpers.js
+++ b/lib/utils/ens-helpers.js
@@ -1,7 +1,10 @@
// @flow
+import uts46 from 'idna-uts46-hx';
+
import { ENSCache } from './ens-cache.js';
import { getETHAddressForUserInfo } from '../shared/account-utils.js';
+import { ensRegex } from '../shared/markdown.js';
type BaseUserInfo = { +username?: ?string, ... };
export type GetENSNames = <T: ?BaseUserInfo>(
@@ -70,4 +73,31 @@
});
}
-export { getENSNames };
+function isValidENSName(name: string): boolean {
+ // While the Ethereum spec allows for more flexibility in ENS names
+ // (see https://eips.ethereum.org/EIPS/eip-137#name-syntax), we want to only
+ // perform lookups on names that adhere to two specific rules:
+ // 1. TLD should be .eth
+ // 2. SLD should be at least three characters in length
+ // Here, we enforce these rules and also use a library similar to the one
+ // recommended by the Ethereum spec to perform the 'heavy lifting' of
+ // making sure the name adheres to all of the specific limitations.
+ try {
+ // Our specific rules on TLDs and SLDs
+ const match = name.match(ensRegex);
+ if (!match) {
+ return false;
+ }
+
+ // Ethereum spec guidelines (throws an error if invalid)
+ uts46.toAscii(name, {
+ transitional: false,
+ useStd3ASCII: true,
+ });
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+export { getENSNames, isValidENSName };
diff --git a/lib/utils/ens-helpers.test.js b/lib/utils/ens-helpers.test.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/ens-helpers.test.js
@@ -0,0 +1,54 @@
+// @flow
+
+import { isValidENSName } from './ens-helpers.js';
+
+describe('it should correctly validate ENS names', () => {
+ it('should match all valid typical ENS names', () => {
+ expect(isValidENSName('foo.eth')).toBe(true);
+ expect(isValidENSName('jack.eth')).toBe(true);
+ expect(isValidENSName('thisuserhasareallylongname.eth')).toBe(true);
+ expect(isValidENSName('hello-world.eth')).toBe(true);
+ });
+
+ it('should match all valid ENS names with numbers', () => {
+ expect(isValidENSName('foo123.eth')).toBe(true);
+ expect(isValidENSName('123foo.eth')).toBe(true);
+ expect(isValidENSName('123foo123.eth')).toBe(true);
+ });
+
+ it('should match all valid ENS names with unicode characters', () => {
+ expect(isValidENSName('föǒ.eth')).toBe(true);
+ expect(isValidENSName('hëllø.eth')).toBe(true);
+ });
+
+ it('should match one-character emoji SLDs that are made up of 3 characters', () => {
+ expect(isValidENSName('💂‍♂️.eth')).toBe(true);
+ expect(isValidENSName('🕵️‍♂️.eth')).toBe(true);
+ expect(isValidENSName('👨‍🚀.eth')).toBe(true);
+ });
+
+ it('should not match one-character emoji SLDs that are made up of less than 3 characters', () => {
+ expect(isValidENSName('🏀.eth')).toBe(false);
+ expect(isValidENSName('🎃.eth')).toBe(false);
+ });
+
+ it('should not match any SLDs less than 3 characters', () => {
+ expect(isValidENSName('fo.eth')).toBe(false);
+ expect(isValidENSName('f.eth')).toBe(false);
+ expect(isValidENSName('')).toBe(false);
+ expect(isValidENSName('a.eth')).toBe(false);
+ expect(isValidENSName('ö.eth')).toBe(false);
+ });
+
+ it('should not match any TLDs other than .eth', () => {
+ expect(isValidENSName('foo.com')).toBe(false);
+ expect(isValidENSName('foo.')).toBe(false);
+ expect(isValidENSName('foo')).toBe(false);
+ });
+
+ it('should not match any names with special characters', () => {
+ expect(isValidENSName('foo.eth!')).toBe(false);
+ expect(isValidENSName('foo.eth#')).toBe(false);
+ expect(isValidENSName('foo$.eth')).toBe(false);
+ });
+});

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 3, 2:20 AM (21 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2609798
Default Alt Text
D9883.diff (4 KB)

Event Timeline