@metamask/snaps-utils 4.0.0 → 4.0.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [4.0.1]
10
+ ### Fixed
11
+ - Change `validateTextLinks` to only get URL in markdown links ([#1914](https://github.com/MetaMask/snaps/pull/1914))
12
+
9
13
  ## [4.0.0]
10
14
  ### Changed
11
15
  - Use `SubtleCrypto` for checksum calculation if available ([#1953](https://github.com/MetaMask/snaps/pull/1953))
@@ -103,7 +107,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
103
107
  - The version of the package no longer needs to match the version of all other
104
108
  MetaMask Snaps packages.
105
109
 
106
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@4.0.0...HEAD
110
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@4.0.1...HEAD
111
+ [4.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@4.0.0...@metamask/snaps-utils@4.0.1
107
112
  [4.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@3.3.0...@metamask/snaps-utils@4.0.0
108
113
  [3.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@3.2.0...@metamask/snaps-utils@3.3.0
109
114
  [3.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@3.1.0...@metamask/snaps-utils@3.2.0
package/dist/cjs/ui.js CHANGED
@@ -18,24 +18,26 @@ _export(exports, {
18
18
  });
19
19
  const _snapssdk = require("@metamask/snaps-sdk");
20
20
  const _utils = require("@metamask/utils");
21
- const LINK_REGEX = RegExp("(?<protocol>[a-z]+:\\/?\\/?)(?<host>\\S+?(?:\\.[a-z]+)+)", "giu");
21
+ const MARKDOWN_LINK_REGEX = RegExp("\\[(?<name>[^\\]]*)\\]\\((?<url>[^)]+)\\)", "giu");
22
22
  const ALLOWED_PROTOCOLS = [
23
23
  'https:',
24
24
  'mailto:'
25
25
  ];
26
26
  function validateTextLinks(text, isOnPhishingList) {
27
- const links = text.match(LINK_REGEX);
28
- if (links) {
29
- links.forEach((link)=>{
30
- try {
31
- const url = new URL(link);
32
- (0, _utils.assert)(ALLOWED_PROTOCOLS.includes(url.protocol), `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`);
33
- const hostname = url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;
34
- (0, _utils.assert)(!isOnPhishingList(hostname), 'The specified URL is not allowed.');
35
- } catch (error) {
36
- throw new Error(`Invalid URL: ${error instanceof _utils.AssertionError ? error.message : 'Unable to parse URL.'}`);
37
- }
38
- });
27
+ const matches = String.prototype.matchAll.call(text, MARKDOWN_LINK_REGEX);
28
+ for (const { groups } of matches){
29
+ const link = groups?.url;
30
+ /* This case should never happen with the regex but the TS type allows for undefined */ /* istanbul ignore next */ if (!link) {
31
+ continue;
32
+ }
33
+ try {
34
+ const url = new URL(link);
35
+ (0, _utils.assert)(ALLOWED_PROTOCOLS.includes(url.protocol), `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`);
36
+ const hostname = url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;
37
+ (0, _utils.assert)(!isOnPhishingList(hostname), 'The specified URL is not allowed.');
38
+ } catch (error) {
39
+ throw new Error(`Invalid URL: ${error instanceof _utils.AssertionError ? error.message : 'Unable to parse URL.'}`);
40
+ }
39
41
  }
40
42
  }
41
43
  function validateComponentLinks(component, isOnPhishingList) {
@@ -43,7 +45,7 @@ function validateComponentLinks(component, isOnPhishingList) {
43
45
  if (type === _snapssdk.NodeType.Panel) {
44
46
  component.children.forEach((node)=>validateComponentLinks(node, isOnPhishingList));
45
47
  }
46
- if ((0, _utils.hasProperty)(component, 'value') && typeof component.value === 'string') {
48
+ if (type === _snapssdk.NodeType.Text) {
47
49
  validateTextLinks(component.value, isOnPhishingList);
48
50
  }
49
51
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-sdk';\nimport { NodeType } from '@metamask/snaps-sdk';\nimport { assert, AssertionError, hasProperty } from '@metamask/utils';\n\nconst LINK_REGEX = /(?<protocol>[a-z]+:\\/?\\/?)(?<host>\\S+?(?:\\.[a-z]+)+)/giu;\nconst ALLOWED_PROTOCOLS = ['https:', 'mailto:'];\n\n/**\n * Search for links in a sting and check them against the phishing list.\n *\n * @param text - The text to verify.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the text contains a link that is not allowed.\n */\nexport function validateTextLinks(\n text: string,\n isOnPhishingList: (url: string) => boolean,\n) {\n const links = text.match(LINK_REGEX);\n if (links) {\n links.forEach((link) => {\n try {\n const url = new URL(link);\n assert(\n ALLOWED_PROTOCOLS.includes(url.protocol),\n `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`,\n );\n\n const hostname =\n url.protocol === 'mailto:'\n ? url.pathname.split('@')[1]\n : url.hostname;\n\n assert(\n !isOnPhishingList(hostname),\n 'The specified URL is not allowed.',\n );\n } catch (error) {\n throw new Error(\n `Invalid URL: ${\n error instanceof AssertionError\n ? error.message\n : 'Unable to parse URL.'\n }`,\n );\n }\n });\n }\n}\n\n/**\n * Search for links in UI components and check that the URL they are trying to\n * pass in is not in the phishing list.\n *\n * @param component - The custom UI component.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the component contains a link that is not allowed.\n */\nexport function validateComponentLinks(\n component: Component,\n isOnPhishingList: (url: string) => boolean,\n) {\n const { type } = component;\n if (type === NodeType.Panel) {\n component.children.forEach((node) =>\n validateComponentLinks(node, isOnPhishingList),\n );\n }\n\n if (hasProperty(component, 'value') && typeof component.value === 'string') {\n validateTextLinks(component.value, isOnPhishingList);\n }\n}\n"],"names":["validateTextLinks","validateComponentLinks","LINK_REGEX","ALLOWED_PROTOCOLS","text","isOnPhishingList","links","match","forEach","link","url","URL","assert","includes","protocol","join","hostname","pathname","split","error","Error","AssertionError","message","component","type","NodeType","Panel","children","node","hasProperty","value"],"mappings":";;;;;;;;;;;IAegBA,iBAAiB;eAAjBA;;IA6CAC,sBAAsB;eAAtBA;;;0BA3DS;uBAC2B;AAEpD,MAAMC,aAAa;AACnB,MAAMC,oBAAoB;IAAC;IAAU;CAAU;AAUxC,SAASH,kBACdI,IAAY,EACZC,gBAA0C;IAE1C,MAAMC,QAAQF,KAAKG,KAAK,CAACL;IACzB,IAAII,OAAO;QACTA,MAAME,OAAO,CAAC,CAACC;YACb,IAAI;gBACF,MAAMC,MAAM,IAAIC,IAAIF;gBACpBG,IAAAA,aAAM,EACJT,kBAAkBU,QAAQ,CAACH,IAAII,QAAQ,GACvC,CAAC,yBAAyB,EAAEX,kBAAkBY,IAAI,CAAC,MAAM,CAAC,CAAC;gBAG7D,MAAMC,WACJN,IAAII,QAAQ,KAAK,YACbJ,IAAIO,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE,GAC1BR,IAAIM,QAAQ;gBAElBJ,IAAAA,aAAM,EACJ,CAACP,iBAAiBW,WAClB;YAEJ,EAAE,OAAOG,OAAO;gBACd,MAAM,IAAIC,MACR,CAAC,aAAa,EACZD,iBAAiBE,qBAAc,GAC3BF,MAAMG,OAAO,GACb,uBACL,CAAC;YAEN;QACF;IACF;AACF;AAWO,SAASrB,uBACdsB,SAAoB,EACpBlB,gBAA0C;IAE1C,MAAM,EAAEmB,IAAI,EAAE,GAAGD;IACjB,IAAIC,SAASC,kBAAQ,CAACC,KAAK,EAAE;QAC3BH,UAAUI,QAAQ,CAACnB,OAAO,CAAC,CAACoB,OAC1B3B,uBAAuB2B,MAAMvB;IAEjC;IAEA,IAAIwB,IAAAA,kBAAW,EAACN,WAAW,YAAY,OAAOA,UAAUO,KAAK,KAAK,UAAU;QAC1E9B,kBAAkBuB,UAAUO,KAAK,EAAEzB;IACrC;AACF"}
1
+ {"version":3,"sources":["../../src/ui.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-sdk';\nimport { NodeType } from '@metamask/snaps-sdk';\nimport { assert, AssertionError } from '@metamask/utils';\n\nconst MARKDOWN_LINK_REGEX = /\\[(?<name>[^\\]]*)\\]\\((?<url>[^)]+)\\)/giu;\n\nconst ALLOWED_PROTOCOLS = ['https:', 'mailto:'];\n\n/**\n * Searches for markdown links in a string and checks them against the phishing list.\n *\n * @param text - The text to verify.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the text contains a link that is not allowed.\n */\nexport function validateTextLinks(\n text: string,\n isOnPhishingList: (url: string) => boolean,\n) {\n const matches = String.prototype.matchAll.call(text, MARKDOWN_LINK_REGEX);\n\n for (const { groups } of matches) {\n const link = groups?.url;\n\n /* This case should never happen with the regex but the TS type allows for undefined */\n /* istanbul ignore next */\n if (!link) {\n continue;\n }\n\n try {\n const url = new URL(link);\n assert(\n ALLOWED_PROTOCOLS.includes(url.protocol),\n `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`,\n );\n\n const hostname =\n url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;\n\n assert(!isOnPhishingList(hostname), 'The specified URL is not allowed.');\n } catch (error) {\n throw new Error(\n `Invalid URL: ${\n error instanceof AssertionError\n ? error.message\n : 'Unable to parse URL.'\n }`,\n );\n }\n }\n}\n\n/**\n * Search for links in UI components and check that the URL they are trying to\n * pass in is not in the phishing list.\n *\n * @param component - The custom UI component.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the component contains a link that is not allowed.\n */\nexport function validateComponentLinks(\n component: Component,\n isOnPhishingList: (url: string) => boolean,\n) {\n const { type } = component;\n if (type === NodeType.Panel) {\n component.children.forEach((node) =>\n validateComponentLinks(node, isOnPhishingList),\n );\n }\n\n if (type === NodeType.Text) {\n validateTextLinks(component.value, isOnPhishingList);\n }\n}\n"],"names":["validateTextLinks","validateComponentLinks","MARKDOWN_LINK_REGEX","ALLOWED_PROTOCOLS","text","isOnPhishingList","matches","String","prototype","matchAll","call","groups","link","url","URL","assert","includes","protocol","join","hostname","pathname","split","error","Error","AssertionError","message","component","type","NodeType","Panel","children","forEach","node","Text","value"],"mappings":";;;;;;;;;;;IAgBgBA,iBAAiB;eAAjBA;;IA+CAC,sBAAsB;eAAtBA;;;0BA9DS;uBACc;AAEvC,MAAMC,sBAAsB;AAE5B,MAAMC,oBAAoB;IAAC;IAAU;CAAU;AAUxC,SAASH,kBACdI,IAAY,EACZC,gBAA0C;IAE1C,MAAMC,UAAUC,OAAOC,SAAS,CAACC,QAAQ,CAACC,IAAI,CAACN,MAAMF;IAErD,KAAK,MAAM,EAAES,MAAM,EAAE,IAAIL,QAAS;QAChC,MAAMM,OAAOD,QAAQE;QAErB,qFAAqF,GACrF,wBAAwB,GACxB,IAAI,CAACD,MAAM;YACT;QACF;QAEA,IAAI;YACF,MAAMC,MAAM,IAAIC,IAAIF;YACpBG,IAAAA,aAAM,EACJZ,kBAAkBa,QAAQ,CAACH,IAAII,QAAQ,GACvC,CAAC,yBAAyB,EAAEd,kBAAkBe,IAAI,CAAC,MAAM,CAAC,CAAC;YAG7D,MAAMC,WACJN,IAAII,QAAQ,KAAK,YAAYJ,IAAIO,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAGR,IAAIM,QAAQ;YAExEJ,IAAAA,aAAM,EAAC,CAACV,iBAAiBc,WAAW;QACtC,EAAE,OAAOG,OAAO;YACd,MAAM,IAAIC,MACR,CAAC,aAAa,EACZD,iBAAiBE,qBAAc,GAC3BF,MAAMG,OAAO,GACb,uBACL,CAAC;QAEN;IACF;AACF;AAWO,SAASxB,uBACdyB,SAAoB,EACpBrB,gBAA0C;IAE1C,MAAM,EAAEsB,IAAI,EAAE,GAAGD;IACjB,IAAIC,SAASC,kBAAQ,CAACC,KAAK,EAAE;QAC3BH,UAAUI,QAAQ,CAACC,OAAO,CAAC,CAACC,OAC1B/B,uBAAuB+B,MAAM3B;IAEjC;IAEA,IAAIsB,SAASC,kBAAQ,CAACK,IAAI,EAAE;QAC1BjC,kBAAkB0B,UAAUQ,KAAK,EAAE7B;IACrC;AACF"}
package/dist/esm/ui.js CHANGED
@@ -1,30 +1,32 @@
1
1
  import { NodeType } from '@metamask/snaps-sdk';
2
- import { assert, AssertionError, hasProperty } from '@metamask/utils';
3
- const LINK_REGEX = RegExp("(?<protocol>[a-z]+:\\/?\\/?)(?<host>\\S+?(?:\\.[a-z]+)+)", "giu");
2
+ import { assert, AssertionError } from '@metamask/utils';
3
+ const MARKDOWN_LINK_REGEX = RegExp("\\[(?<name>[^\\]]*)\\]\\((?<url>[^)]+)\\)", "giu");
4
4
  const ALLOWED_PROTOCOLS = [
5
5
  'https:',
6
6
  'mailto:'
7
7
  ];
8
8
  /**
9
- * Search for links in a sting and check them against the phishing list.
9
+ * Searches for markdown links in a string and checks them against the phishing list.
10
10
  *
11
11
  * @param text - The text to verify.
12
12
  * @param isOnPhishingList - The function that checks the link against the
13
13
  * phishing list.
14
14
  * @throws If the text contains a link that is not allowed.
15
15
  */ export function validateTextLinks(text, isOnPhishingList) {
16
- const links = text.match(LINK_REGEX);
17
- if (links) {
18
- links.forEach((link)=>{
19
- try {
20
- const url = new URL(link);
21
- assert(ALLOWED_PROTOCOLS.includes(url.protocol), `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`);
22
- const hostname = url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;
23
- assert(!isOnPhishingList(hostname), 'The specified URL is not allowed.');
24
- } catch (error) {
25
- throw new Error(`Invalid URL: ${error instanceof AssertionError ? error.message : 'Unable to parse URL.'}`);
26
- }
27
- });
16
+ const matches = String.prototype.matchAll.call(text, MARKDOWN_LINK_REGEX);
17
+ for (const { groups } of matches){
18
+ const link = groups?.url;
19
+ /* This case should never happen with the regex but the TS type allows for undefined */ /* istanbul ignore next */ if (!link) {
20
+ continue;
21
+ }
22
+ try {
23
+ const url = new URL(link);
24
+ assert(ALLOWED_PROTOCOLS.includes(url.protocol), `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`);
25
+ const hostname = url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;
26
+ assert(!isOnPhishingList(hostname), 'The specified URL is not allowed.');
27
+ } catch (error) {
28
+ throw new Error(`Invalid URL: ${error instanceof AssertionError ? error.message : 'Unable to parse URL.'}`);
29
+ }
28
30
  }
29
31
  }
30
32
  /**
@@ -40,7 +42,7 @@ const ALLOWED_PROTOCOLS = [
40
42
  if (type === NodeType.Panel) {
41
43
  component.children.forEach((node)=>validateComponentLinks(node, isOnPhishingList));
42
44
  }
43
- if (hasProperty(component, 'value') && typeof component.value === 'string') {
45
+ if (type === NodeType.Text) {
44
46
  validateTextLinks(component.value, isOnPhishingList);
45
47
  }
46
48
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-sdk';\nimport { NodeType } from '@metamask/snaps-sdk';\nimport { assert, AssertionError, hasProperty } from '@metamask/utils';\n\nconst LINK_REGEX = /(?<protocol>[a-z]+:\\/?\\/?)(?<host>\\S+?(?:\\.[a-z]+)+)/giu;\nconst ALLOWED_PROTOCOLS = ['https:', 'mailto:'];\n\n/**\n * Search for links in a sting and check them against the phishing list.\n *\n * @param text - The text to verify.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the text contains a link that is not allowed.\n */\nexport function validateTextLinks(\n text: string,\n isOnPhishingList: (url: string) => boolean,\n) {\n const links = text.match(LINK_REGEX);\n if (links) {\n links.forEach((link) => {\n try {\n const url = new URL(link);\n assert(\n ALLOWED_PROTOCOLS.includes(url.protocol),\n `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`,\n );\n\n const hostname =\n url.protocol === 'mailto:'\n ? url.pathname.split('@')[1]\n : url.hostname;\n\n assert(\n !isOnPhishingList(hostname),\n 'The specified URL is not allowed.',\n );\n } catch (error) {\n throw new Error(\n `Invalid URL: ${\n error instanceof AssertionError\n ? error.message\n : 'Unable to parse URL.'\n }`,\n );\n }\n });\n }\n}\n\n/**\n * Search for links in UI components and check that the URL they are trying to\n * pass in is not in the phishing list.\n *\n * @param component - The custom UI component.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the component contains a link that is not allowed.\n */\nexport function validateComponentLinks(\n component: Component,\n isOnPhishingList: (url: string) => boolean,\n) {\n const { type } = component;\n if (type === NodeType.Panel) {\n component.children.forEach((node) =>\n validateComponentLinks(node, isOnPhishingList),\n );\n }\n\n if (hasProperty(component, 'value') && typeof component.value === 'string') {\n validateTextLinks(component.value, isOnPhishingList);\n }\n}\n"],"names":["NodeType","assert","AssertionError","hasProperty","LINK_REGEX","ALLOWED_PROTOCOLS","validateTextLinks","text","isOnPhishingList","links","match","forEach","link","url","URL","includes","protocol","join","hostname","pathname","split","error","Error","message","validateComponentLinks","component","type","Panel","children","node","value"],"mappings":"AACA,SAASA,QAAQ,QAAQ,sBAAsB;AAC/C,SAASC,MAAM,EAAEC,cAAc,EAAEC,WAAW,QAAQ,kBAAkB;AAEtE,MAAMC,aAAa;AACnB,MAAMC,oBAAoB;IAAC;IAAU;CAAU;AAE/C;;;;;;;CAOC,GACD,OAAO,SAASC,kBACdC,IAAY,EACZC,gBAA0C;IAE1C,MAAMC,QAAQF,KAAKG,KAAK,CAACN;IACzB,IAAIK,OAAO;QACTA,MAAME,OAAO,CAAC,CAACC;YACb,IAAI;gBACF,MAAMC,MAAM,IAAIC,IAAIF;gBACpBX,OACEI,kBAAkBU,QAAQ,CAACF,IAAIG,QAAQ,GACvC,CAAC,yBAAyB,EAAEX,kBAAkBY,IAAI,CAAC,MAAM,CAAC,CAAC;gBAG7D,MAAMC,WACJL,IAAIG,QAAQ,KAAK,YACbH,IAAIM,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE,GAC1BP,IAAIK,QAAQ;gBAElBjB,OACE,CAACO,iBAAiBU,WAClB;YAEJ,EAAE,OAAOG,OAAO;gBACd,MAAM,IAAIC,MACR,CAAC,aAAa,EACZD,iBAAiBnB,iBACbmB,MAAME,OAAO,GACb,uBACL,CAAC;YAEN;QACF;IACF;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASC,uBACdC,SAAoB,EACpBjB,gBAA0C;IAE1C,MAAM,EAAEkB,IAAI,EAAE,GAAGD;IACjB,IAAIC,SAAS1B,SAAS2B,KAAK,EAAE;QAC3BF,UAAUG,QAAQ,CAACjB,OAAO,CAAC,CAACkB,OAC1BL,uBAAuBK,MAAMrB;IAEjC;IAEA,IAAIL,YAAYsB,WAAW,YAAY,OAAOA,UAAUK,KAAK,KAAK,UAAU;QAC1ExB,kBAAkBmB,UAAUK,KAAK,EAAEtB;IACrC;AACF"}
1
+ {"version":3,"sources":["../../src/ui.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-sdk';\nimport { NodeType } from '@metamask/snaps-sdk';\nimport { assert, AssertionError } from '@metamask/utils';\n\nconst MARKDOWN_LINK_REGEX = /\\[(?<name>[^\\]]*)\\]\\((?<url>[^)]+)\\)/giu;\n\nconst ALLOWED_PROTOCOLS = ['https:', 'mailto:'];\n\n/**\n * Searches for markdown links in a string and checks them against the phishing list.\n *\n * @param text - The text to verify.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the text contains a link that is not allowed.\n */\nexport function validateTextLinks(\n text: string,\n isOnPhishingList: (url: string) => boolean,\n) {\n const matches = String.prototype.matchAll.call(text, MARKDOWN_LINK_REGEX);\n\n for (const { groups } of matches) {\n const link = groups?.url;\n\n /* This case should never happen with the regex but the TS type allows for undefined */\n /* istanbul ignore next */\n if (!link) {\n continue;\n }\n\n try {\n const url = new URL(link);\n assert(\n ALLOWED_PROTOCOLS.includes(url.protocol),\n `Protocol must be one of: ${ALLOWED_PROTOCOLS.join(', ')}.`,\n );\n\n const hostname =\n url.protocol === 'mailto:' ? url.pathname.split('@')[1] : url.hostname;\n\n assert(!isOnPhishingList(hostname), 'The specified URL is not allowed.');\n } catch (error) {\n throw new Error(\n `Invalid URL: ${\n error instanceof AssertionError\n ? error.message\n : 'Unable to parse URL.'\n }`,\n );\n }\n }\n}\n\n/**\n * Search for links in UI components and check that the URL they are trying to\n * pass in is not in the phishing list.\n *\n * @param component - The custom UI component.\n * @param isOnPhishingList - The function that checks the link against the\n * phishing list.\n * @throws If the component contains a link that is not allowed.\n */\nexport function validateComponentLinks(\n component: Component,\n isOnPhishingList: (url: string) => boolean,\n) {\n const { type } = component;\n if (type === NodeType.Panel) {\n component.children.forEach((node) =>\n validateComponentLinks(node, isOnPhishingList),\n );\n }\n\n if (type === NodeType.Text) {\n validateTextLinks(component.value, isOnPhishingList);\n }\n}\n"],"names":["NodeType","assert","AssertionError","MARKDOWN_LINK_REGEX","ALLOWED_PROTOCOLS","validateTextLinks","text","isOnPhishingList","matches","String","prototype","matchAll","call","groups","link","url","URL","includes","protocol","join","hostname","pathname","split","error","Error","message","validateComponentLinks","component","type","Panel","children","forEach","node","Text","value"],"mappings":"AACA,SAASA,QAAQ,QAAQ,sBAAsB;AAC/C,SAASC,MAAM,EAAEC,cAAc,QAAQ,kBAAkB;AAEzD,MAAMC,sBAAsB;AAE5B,MAAMC,oBAAoB;IAAC;IAAU;CAAU;AAE/C;;;;;;;CAOC,GACD,OAAO,SAASC,kBACdC,IAAY,EACZC,gBAA0C;IAE1C,MAAMC,UAAUC,OAAOC,SAAS,CAACC,QAAQ,CAACC,IAAI,CAACN,MAAMH;IAErD,KAAK,MAAM,EAAEU,MAAM,EAAE,IAAIL,QAAS;QAChC,MAAMM,OAAOD,QAAQE;QAErB,qFAAqF,GACrF,wBAAwB,GACxB,IAAI,CAACD,MAAM;YACT;QACF;QAEA,IAAI;YACF,MAAMC,MAAM,IAAIC,IAAIF;YACpBb,OACEG,kBAAkBa,QAAQ,CAACF,IAAIG,QAAQ,GACvC,CAAC,yBAAyB,EAAEd,kBAAkBe,IAAI,CAAC,MAAM,CAAC,CAAC;YAG7D,MAAMC,WACJL,IAAIG,QAAQ,KAAK,YAAYH,IAAIM,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAGP,IAAIK,QAAQ;YAExEnB,OAAO,CAACM,iBAAiBa,WAAW;QACtC,EAAE,OAAOG,OAAO;YACd,MAAM,IAAIC,MACR,CAAC,aAAa,EACZD,iBAAiBrB,iBACbqB,MAAME,OAAO,GACb,uBACL,CAAC;QAEN;IACF;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASC,uBACdC,SAAoB,EACpBpB,gBAA0C;IAE1C,MAAM,EAAEqB,IAAI,EAAE,GAAGD;IACjB,IAAIC,SAAS5B,SAAS6B,KAAK,EAAE;QAC3BF,UAAUG,QAAQ,CAACC,OAAO,CAAC,CAACC,OAC1BN,uBAAuBM,MAAMzB;IAEjC;IAEA,IAAIqB,SAAS5B,SAASiC,IAAI,EAAE;QAC1B5B,kBAAkBsB,UAAUO,KAAK,EAAE3B;IACrC;AACF"}
@@ -1,6 +1,6 @@
1
1
  import type { Component } from '@metamask/snaps-sdk';
2
2
  /**
3
- * Search for links in a sting and check them against the phishing list.
3
+ * Searches for markdown links in a string and checks them against the phishing list.
4
4
  *
5
5
  * @param text - The text to verify.
6
6
  * @param isOnPhishingList - The function that checks the link against the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-utils",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/MetaMask/snaps.git"
@@ -72,7 +72,7 @@
72
72
  "@metamask/permission-controller": "^5.0.0",
73
73
  "@metamask/rpc-errors": "^6.1.0",
74
74
  "@metamask/snaps-registry": "^2.1.0",
75
- "@metamask/snaps-sdk": "^1.0.0",
75
+ "@metamask/snaps-sdk": "^1.1.0",
76
76
  "@metamask/utils": "^8.1.0",
77
77
  "@noble/hashes": "^1.3.1",
78
78
  "@scure/base": "^1.1.1",