CVE-2023-40580: Insufficient Information (NVD-CWE-noinfo)
value: Freighter is a Stellar chrome extension. It may be possible for a malicious website to access the recovery mnemonic phrase when the Freighter wallet is unlocked. This vulnerability impacts access control to the mnemonic recovery phrase. This issue was patched in version 5.3.1.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 6.5
Published: 2023-08-25T20:15Z
Repository: https://github.com/stellar/freighter
Language: Other
Files changed: @shared/api/internal.ts, extension/package.json, extension/public/static/manifest/v2.json, extension/public/static/manifest/v3.json, extension/src/background/messageListener/popupMessageListener.ts, extension/src/popup/Router.tsx, extension/src/popup/components/Onboarding/index.tsx, extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx, extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx, extension/src/popup/views/AccountCreator/index.tsx, extension/src/popup/views/DisplayBackupPhrase/index.tsx, extension/src/popup/views/MnemonicPhrase.tsx, extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx
Commit date: 2023-08-23 12:10:20 -0400
Commit message: Prevent Javascript from accessing the mnemonic phrase through a private API (#948)


Diff: diff --git a/@shared/api/internal.ts b/@shared/api/internal.ts
index 4e55ef7..44f0368 100644
--- a/@shared/api/internal.ts
+++ b/@shared/api/internal.ts
@@ -668,12 +668,12 @@ export const signOut = async (): Promise<{
   return response;
 };
 
 export const showBackupPhrase = async (
   password: string,
-): Promise<{ error: string }> => {
-  let response = { error: "" };
+): Promise<{ mnemonicPhrase: string; error: string }> => {
+  let response = { mnemonicPhrase: "", error: "" };
   try {
     response = await sendMessageToBackground({
       password,
       type: SERVICE_TYPES.SHOW_BACKUP_PHRASE,
     });
diff --git a/extension/package.json b/extension/package.json
index 9545a58..0494617 100755
--- a/extension/package.json
+++ b/extension/package.json
@@ -1,8 +1,8 @@
 {
   "name": "extension",
-  "version": "5.3.0",
+  "version": "5.3.1",
   "license": "Apache-2.0",
   "prettier": "@stellar/prettier-config",
   "scripts": {
     "setup": "yarn install && yarn allow-scripts",
     "build": "webpack --config webpack.extension.js",
diff --git a/extension/public/static/manifest/v2.json b/extension/public/static/manifest/v2.json
index 1179b0a..206ec4b 100644
--- a/extension/public/static/manifest/v2.json
+++ b/extension/public/static/manifest/v2.json
@@ -1,9 +1,9 @@
 {
   "name": "Freighter",
-  "version": "5.3.0",
-  "version_name": "5.3.0",
+  "version": "5.3.1",
+  "version_name": "5.3.1",
   "description": "Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser.",
   "browser_specific_settings": {
     "gecko": {
       "id": "{3ee0dd4e-8c64-4b92-b539-25718a10f62f}",
       "strict_min_version": "48.0"
diff --git a/extension/public/static/manifest/v3.json b/extension/public/static/manifest/v3.json
index 0c7622f..3985a30 100644
--- a/extension/public/static/manifest/v3.json
+++ b/extension/public/static/manifest/v3.json
@@ -1,9 +1,9 @@
 {
   "name": "Freighter",
-  "version": "5.3.0",
-  "version_name": "5.3.0",
+  "version": "5.3.1",
+  "version_name": "5.3.1",
   "description": "Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser.",
   "background": {
     "service_worker": "background.min.js"
   },
   "content_scripts": [
diff --git a/extension/src/background/messageListener/popupMessageListener.ts b/extension/src/background/messageListener/popupMessageListener.ts
index cebb21e..905fa4f 100644
--- a/extension/src/background/messageListener/popupMessageListener.ts
+++ b/extension/src/background/messageListener/popupMessageListener.ts
@@ -581,13 +581,27 @@ export const popupMessageListener = (request: Request, sessionStore: Store) => {
       bipPath: await getBipPath(),
       tokenIdList: (await localStore.getItem(TOKEN_ID_LIST)) || {},
     };
   };
 
-  const getMnemonicPhrase = () => ({
-    mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
-  });
+  const getMnemonicPhrase = async () => {
+    const { password } = request;
+
+    const keyID = (await getIsHardwareWalletActive())
+      ? await _getNonHwKeyID()
+      : (await localStore.getItem(KEY_ID)) || "";
+
+    try {
+      await _unlockKeystore({ keyID, password });
+    } catch (e) {
+      console.error(e);
+      return { error: "Incorrect password" };
+    }
+    return {
+      mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
+    };
+  };
 
   const confirmMnemonicPhrase = async () => {
     const isCorrectPhrase =
       mnemonicPhraseSelector(sessionStore.getState()) ===
       request.mnemonicPhraseToConfirm;
@@ -696,14 +710,17 @@ export const popupMessageListener = (request: Request, sessionStore: Store) => {
     try {
       await _unlockKeystore({
         keyID: (await localStore.getItem(KEY_ID)) || "",
         password,
       });
-      return {};
     } catch (e) {
       return { error: "Incorrect Password" };
     }
+
+    return {
+      mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
+    };
   };
 
   const _getLocalStorageAccounts = async (password: string) => {
     const keyIdList = await getKeyIdList();
     const accountNameList = await getAccountNameList();
diff --git a/extension/src/popup/Router.tsx b/extension/src/popup/Router.tsx
index c14598d..3a3c1c4 100644
--- a/extension/src/popup/Router.tsx
+++ b/extension/src/popup/Router.tsx
@@ -281,11 +281,11 @@ export const Router = () => {
         </PublicKeyRoute>
         <PublicKeyRoute path={ROUTES.grantAccess}>
           <GrantAccess />
         </PublicKeyRoute>
         <PublicKeyRoute path={ROUTES.mnemonicPhrase}>
-          <MnemonicPhrase />
+          <MnemonicPhrase mnemonicPhrase="" />
         </PublicKeyRoute>
         <PublicKeyRoute path={ROUTES.settings} exact>
           <Settings />
         </PublicKeyRoute>
         <PublicKeyRoute path={ROUTES.preferences}>
diff --git a/extension/src/popup/components/Onboarding/index.tsx b/extension/src/popup/components/Onboarding/index.tsx
index 543cbe5..8a9359a 100644
--- a/extension/src/popup/components/Onboarding/index.tsx
+++ b/extension/src/popup/components/Onboarding/index.tsx
@@ -4,24 +4,26 @@ import { useHistory } from "react-router-dom";
 import { BackButton } from "popup/basics/buttons/BackButton";
 
 import "./styles.scss";
 
 export const Onboarding = ({
+  customBackAction,
   hasGoBackBtn,
   children,
 }: {
+  customBackAction?: () => void;
   hasGoBackBtn?: boolean;
   children: React.ReactNode;
 }) => {
   const history = useHistory();
   const isNewTabSession = history.length === 1;
 
   return (
     <div className="Onboarding">
       {hasGoBackBtn && !isNewTabSession ? (
         <div className="Onboarding--back">
-          <BackButton hasBackCopy />
+          <BackButton customBackAction={customBackAction} hasBackCopy />
         </div>
       ) : null}
       {children}
     </div>
   );
diff --git a/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx b/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx
index e2578e1..303d3c5 100644
--- a/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx
+++ b/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx
@@ -1,12 +1,10 @@
 import React from "react";
 import { useTranslation } from "react-i18next";
 
 import { InfoBlock } from "popup/basics/InfoBlock";
 import { Button } from "popup/basics/buttons/Button";
-import { ROUTES } from "popup/constants/routes";
-import { navigateTo } from "popup/helpers/navigate";
 
 import {
   OnboardingScreen,
   OnboardingHalfScreen,
   OnboardingHeader,
@@ -16,12 +14,14 @@ import { MnemonicDisplay } from "../MnemonicDisplay";
 
 import "./styles.scss";
 
 export const DisplayMnemonicPhrase = ({
   mnemonicPhrase,
+  setIsConfirmed,
 }: {
   mnemonicPhrase: string;
+  setIsConfirmed: (confirmed: boolean) => void;
 }) => {
   const { t } = useTranslation();
 
   return (
     <div
@@ -58,11 +58,11 @@ export const DisplayMnemonicPhrase = ({
           <MnemonicDisplay mnemonicPhrase={mnemonicPhrase} />
           <Button
             data-testid="display-mnemonic-phrase-next-btn"
             fullWidth
             onClick={() => {
-              navigateTo(ROUTES.mnemonicPhraseConfirm);
+              setIsConfirmed(true);
             }}
           >
             {t("Next")}
           </Button>
         </OnboardingHalfScreen>
diff --git a/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx b/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx
index a145adb..8b6d47e 100644
--- a/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx
+++ b/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx
@@ -9,11 +9,11 @@ import "./styles.scss";
 interface generateMnemonicPhraseDisplayProps {
   mnemonicPhrase: string;
 }
 
 export const generateMnemonicPhraseDisplay = ({
-  mnemonicPhrase,
+  mnemonicPhrase = "",
 }: generateMnemonicPhraseDisplayProps) =>
   mnemonicPhrase.split(" ").map((word: string) => {
     /* 
       As a security measure, we want to prevent writing the mnemonic phrase to the DOM. 
       The browser can leak this string into memory where a hacker could possibly access it.
diff --git a/extension/src/popup/helpers/useMnemonicPhrase.ts b/extension/src/popup/helpers/useMnemonicPhrase.ts
deleted file mode 100644
index 33cb92b..0000000
--- a/extension/src/popup/helpers/useMnemonicPhrase.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { useEffect, useState } from "react";
-import { getMnemonicPhrase } from "@shared/api/internal";
-
-export const useMnemonicPhrase = () => {
-  const [mnemonicPhrase, setMnemonicPhrase] = useState("");
-
-  useEffect(() => {
-    let res = { mnemonicPhrase: "" };
-
-    const fetchMnemonicPhrase = async () => {
-      try {
-        res = await getMnemonicPhrase();
-      } catch (e) {
-        console.error(e);
-      }
-
-      const { mnemonicPhrase: fetchedMnemonicPhrase } = res;
-      setMnemonicPhrase(fetchedMnemonicPhrase);
-    };
-
-    fetchMnemonicPhrase();
-
-    return () => {
-      setMnemonicPhrase("");
-    };
-  }, []);
-
-  return mnemonicPhrase;
-};
diff --git a/extension/src/popup/views/AccountCreator/index.tsx b/extension/src/popup/views/AccountCreator/index.tsx
index 5c3489d..d35380d 100644
--- a/extension/src/popup/views/AccountCreator/index.tsx
+++ b/extension/src/popup/views/AccountCreator/index.tsx
@@ -1,15 +1,14 @@
-import React, { useEffect } from "react";
+import React, { useState } from "react";
 import { useDispatch, useSelector } from "react-redux";
 import { Input, Checkbox, TextLink } from "@stellar/design-system";
 import { Field, FieldProps, Formik, Form } from "formik";
 import { object as YupObject } from "yup";
 import { useTranslation } from "react-i18next";
 
+import { showBackupPhrase } from "@shared/api/internal";
 import { Button } from "popup/basics/buttons/Button";
-import { ROUTES } from "popup/constants/routes";
-import { navigateTo } from "popup/helpers/navigate";
 import {
   password as passwordValidator,
   confirmPassword as confirmPasswordValidator,
   termsOfUse as termsofUseValidator,
 } from "popup/helpers/validators";
@@ -28,17 +27,20 @@ import {
   OnboardingHeader,
 } from "popup/components/Onboarding";
 import { Header } from "popup/components/Header";
 import { PasswordRequirements } from "popup/components/PasswordRequirements";
 
+import { MnemonicPhrase } from "popup/views/MnemonicPhrase";
+
 import "./styles.scss";
 
 export const AccountCreator = () => {
   const publicKey = useSelector(publicKeySelector);
   const dispatch = useDispatch();
   const authError = useSelector(authErrorSelector);
   const { t } = useTranslation();
+  const [mnemonicPhrase, setMnemonicPhrase] = useState("");
 
   interface FormValues {
     password: string;
     confirmPassword: string;
     termsOfUse: boolean;
@@ -50,25 +52,24 @@ export const AccountCreator = () => {
     termsOfUse: false,
   };
 
   const handleSubmit = async (values: FormValues) => {
     await dispatch(createAccount(values.password));
+    const res = await showBackupPhrase(values.password);
+
+    setMnemonicPhrase(res.mnemonicPhrase);
   };
 
   const AccountCreatorSchema = YupObject().shape({
     password: passwordValidator,
     confirmPassword: confirmPasswordValidator,
     termsOfUse: termsofUseValidator,
   });
 
-  useEffect(() => {
-    if (publicKey) {
-      navigateTo(ROUTES.mnemonicPhrase);
-    }
-  }, [publicKey]);
-
-  return (
+  return mnemonicPhrase && publicKey ? (
+    <MnemonicPhrase mnemonicPhrase={mnemonicPhrase} />
+  ) : (
     <>
       <FullscreenStyle />
       <Header />
       <Onboarding hasGoBackBtn>
         <OnboardingScreen className="AccountCreator__screen">
diff --git a/extension/src/popup/views/DisplayBackupPhrase/index.tsx b/extension/src/popup/views/DisplayBackupPhrase/index.tsx
index 486dcf5..d77d4ab 100644
--- a/extension/src/popup/views/DisplayBackupPhrase/index.tsx
+++ b/extension/src/popup/views/DisplayBackupPhrase/index.tsx
@@ -7,11 +7,10 @@ import { showBackupPhrase } from "@shared/api/internal";
 
 import { ROUTES } from "popup/constants/routes";
 import { Button } from "popup/basics/buttons/Button";
 import { navigateTo } from "popup/helpers/navigate";
 import { emitMetric } from "helpers/metrics";
-import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase";
 
 import { METRIC_NAMES } from "popup/constants/metricsNames";
 
 import { MnemonicDisplay } from "popup/components/mnemonicPhrase/MnemonicDisplay";
 import { SubviewHeader } from "popup/components/SubviewHeader";
@@ -22,11 +21,11 @@ import "./styles.scss";
 
 export const DisplayBackupPhrase = () => {
   const { t } = useTranslation();
   const [errorMessage, setErrorMessage] = useState("");
   const [isPhraseUnlocked, setIsPhraseUnlocked] = useState(false);
-  const mnemonicPhrase = useMnemonicPhrase();
+  const [mnemonicPhrase, setMnemonicPhrase] = useState("");
 
   useEffect(() => {
     emitMetric(
       isPhraseUnlocked
         ? METRIC_NAMES.viewDisplayBackupPhrase
@@ -49,10 +48,11 @@ export const DisplayBackupPhrase = () => {
       setErrorMessage(res.error);
       emitMetric(METRIC_NAMES.backupPhraseFail, {
         error_type: res.error,
       });
     } else {
+      setMnemonicPhrase(res.mnemonicPhrase);
       setIsPhraseUnlocked(true);
       setErrorMessage("");
       emitMetric(METRIC_NAMES.backupPhraseSuccess);
     }
   };
diff --git a/extension/src/popup/views/MnemonicPhrase.tsx b/extension/src/popup/views/MnemonicPhrase.tsx
index aee2d8f..b75934c 100644
--- a/extension/src/popup/views/MnemonicPhrase.tsx
+++ b/extension/src/popup/views/MnemonicPhrase.tsx
@@ -1,48 +1,54 @@
-import React from "react";
+import React, { useState } from "react";
 import { useSelector } from "react-redux";
 import shuffle from "lodash/shuffle";
-import { Switch, Redirect } from "react-router-dom";
+import { Redirect } from "react-router-dom";
 
 import { APPLICATION_STATE } from "@shared/constants/applicationState";
 
-import { PublicKeyRoute } from "popup/Router";
 import { ROUTES } from "popup/constants/routes";
 import { FullscreenStyle } from "popup/components/FullscreenStyle";
-import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase";
 import { Header } from "popup/components/Header";
 import { Onboarding } from "popup/components/Onboarding";
 import { ConfirmMnemonicPhrase } from "popup/components/mnemonicPhrase/ConfirmMnemonicPhrase";
 import { DisplayMnemonicPhrase } from "popup/components/mnemonicPhrase/DisplayMnemonicPhrase";
 import { applicationStateSelector } from "popup/ducks/accountServices";
 
-export const MnemonicPhrase = () => {
-  const mnemonicPhrase = useMnemonicPhrase();
+interface MnemonicPhraseProps {
+  mnemonicPhrase: string;
+}
+
+export const MnemonicPhrase = ({
+  mnemonicPhrase = "",
+}: MnemonicPhraseProps) => {
   const applicationState = useSelector(applicationStateSelector);
+  const [isConfirmed, setIsConfirmed] = useState(false);
 
   if (applicationState === APPLICATION_STATE.MNEMONIC_PHRASE_CONFIRMED) {
     return <Redirect to={ROUTES.pinExtension} />;
   }
 
   if (mnemonicPhrase) {
-    return (
-      <Switch>
-        <PublicKeyRoute exact path={ROUTES.mnemonicPhrase}>
-          <Header />
-          <FullscreenStyle />
-          <Onboarding>
-            <DisplayMnemonicPhrase mnemonicPhrase={mnemonicPhrase} />
-          </Onboarding>
-        </PublicKeyRoute>
-        <PublicKeyRoute exact path={ROUTES.mnemonicPhraseConfirm}>
-          <Header />
-          <FullscreenStyle />
-          <Onboarding hasGoBackBtn>
-            <ConfirmMnemonicPhrase words={shuffle(mnemonicPhrase.split(" "))} />
-          </Onboarding>
-        </PublicKeyRoute>
-      </Switch>
+    return isConfirmed ? (
+      <>
+        <Header />
+        <FullscreenStyle />
+        <Onboarding customBackAction={() => setIsConfirmed(false)} hasGoBackBtn>
+          <ConfirmMnemonicPhrase words={shuffle(mnemonicPhrase.split(" "))} />
+        </Onboarding>
+      </>
+    ) : (
+      <>
+        <Header />
+        <FullscreenStyle />
+        <Onboarding>
+          <DisplayMnemonicPhrase
+            mnemonicPhrase={mnemonicPhrase}
+            setIsConfirmed={setIsConfirmed}
+          />
+        </Onboarding>
+      </>
     );
   }
 
   return null;
 };
diff --git a/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx b/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx
index dc468d3..afcb43c 100644
--- a/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx
+++ b/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx
@@ -25,13 +25,10 @@ jest.mock("popup/constants/history", () => ({
   get history() {
     return mockHistoryGetter();
   },
 }));
 
-jest.mock("popup/helpers/useMnemonicPhrase", () => ({
-  useMnemonicPhrase: () => "dummy mnemonic",
-}));
 jest.mock("react-router-dom", () => {
   const ReactRouter = jest.requireActual("react-router-dom");
   return {
     ...ReactRouter,
     Redirect: ({ to }: any) => <div>redirect {to}</div>,
@@ -66,11 +63,11 @@ describe.skip("MnemonicPhrase", () => {
           settings: {
             networkDetails: TESTNET_NETWORK_DETAILS,
           },
         }}
       >
-        <MnemonicPhrase />
+        <MnemonicPhrase mnemonicPhrase={MNEMONIC} />
       </Wrapper>,
     );
     await waitFor(() => screen.getByTestId("display-mnemonic-phrase"));
     expect(screen.getByTestId("display-mnemonic-phrase")).toBeDefined();
   });
@@ -94,11 +91,11 @@ describe.skip("MnemonicPhrase", () => {
             settings: {
               networkDetails: TESTNET_NETWORK_DETAILS,
             },
           }}
         >
-          <MnemonicPhrase />
+          <MnemonicPhrase mnemonicPhrase={MNEMONIC} />
         </Wrapper>,
       );
 
       // Confirm mnemonic
       await act(async () => {

Vulnerable code: ): Promise<{ error: string }> => {
  let response = { error: "" };
  "version": "5.3.0",
  "version": "5.3.0",
  "version_name": "5.3.0",
  "version": "5.3.0",
  "version_name": "5.3.0",
  const getMnemonicPhrase = () => ({
    mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
  });
      return {};
          <MnemonicPhrase />
          <BackButton hasBackCopy />
import { ROUTES } from "popup/constants/routes";
import { navigateTo } from "popup/helpers/navigate";
              navigateTo(ROUTES.mnemonicPhraseConfirm);
  mnemonicPhrase,
import { useEffect, useState } from "react";
import { getMnemonicPhrase } from "@shared/api/internal";

export const useMnemonicPhrase = () => {
  const [mnemonicPhrase, setMnemonicPhrase] = useState("");

  useEffect(() => {
    let res = { mnemonicPhrase: "" };

    const fetchMnemonicPhrase = async () => {
      try {
        res = await getMnemonicPhrase();
      } catch (e) {
        console.error(e);
      }

      const { mnemonicPhrase: fetchedMnemonicPhrase } = res;
      setMnemonicPhrase(fetchedMnemonicPhrase);
    };

    fetchMnemonicPhrase();

    return () => {
      setMnemonicPhrase("");
    };
  }, []);

  return mnemonicPhrase;
};
import React, { useEffect } from "react";
import { ROUTES } from "popup/constants/routes";
import { navigateTo } from "popup/helpers/navigate";
  useEffect(() => {
    if (publicKey) {
      navigateTo(ROUTES.mnemonicPhrase);
    }
  }, [publicKey]);

  return (
import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase";
  const mnemonicPhrase = useMnemonicPhrase();
import React from "react";
import { Switch, Redirect } from "react-router-dom";
import { PublicKeyRoute } from "popup/Router";
import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase";
export const MnemonicPhrase = () => {
  const mnemonicPhrase = useMnemonicPhrase();
    return (
      <Switch>
        <PublicKeyRoute exact path={ROUTES.mnemonicPhrase}>
          <Header />
          <FullscreenStyle />
          <Onboarding>
            <DisplayMnemonicPhrase mnemonicPhrase={mnemonicPhrase} />
          </Onboarding>
        </PublicKeyRoute>
        <PublicKeyRoute exact path={ROUTES.mnemonicPhraseConfirm}>
          <Header />
          <FullscreenStyle />
          <Onboarding hasGoBackBtn>
            <ConfirmMnemonicPhrase words={shuffle(mnemonicPhrase.split(" "))} />
          </Onboarding>
        </PublicKeyRoute>
      </Switch>
jest.mock("popup/helpers/useMnemonicPhrase", () => ({
  useMnemonicPhrase: () => "dummy mnemonic",
}));
        <MnemonicPhrase />
          <MnemonicPhrase />
Fixed code: ): Promise<{ mnemonicPhrase: string; error: string }> => {
  let response = { mnemonicPhrase: "", error: "" };
  "version": "5.3.1",
  "version": "5.3.1",
  "version_name": "5.3.1",
  "version": "5.3.1",
  "version_name": "5.3.1",
  const getMnemonicPhrase = async () => {
    const { password } = request;

    const keyID = (await getIsHardwareWalletActive())
      ? await _getNonHwKeyID()
      : (await localStore.getItem(KEY_ID)) || "";

    try {
      await _unlockKeystore({ keyID, password });
    } catch (e) {
      console.error(e);
      return { error: "Incorrect password" };
    }
    return {
      mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
    };
  };

    return {
      mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()),
    };
          <MnemonicPhrase mnemonicPhrase="" />
  customBackAction,
  customBackAction?: () => void;
          <BackButton customBackAction={customBackAction} hasBackCopy />
  setIsConfirmed,
  setIsConfirmed: (confirmed: boolean) => void;
              setIsConfirmed(true);
  mnemonicPhrase = "",
import React, { useState } from "react";
import { showBackupPhrase } from "@shared/api/internal";
import { MnemonicPhrase } from "popup/views/MnemonicPhrase";

  const [mnemonicPhrase, setMnemonicPhrase] = useState("");
    const res = await showBackupPhrase(values.password);

    setMnemonicPhrase(res.mnemonicPhrase);
  return mnemonicPhrase && publicKey ? (
    <MnemonicPhrase mnemonicPhrase={mnemonicPhrase} />
  ) : (
  const [mnemonicPhrase, setMnemonicPhrase] = useState("");
      setMnemonicPhrase(res.mnemonicPhrase);
import React, { useState } from "react";
import { Redirect } from "react-router-dom";
interface MnemonicPhraseProps {
  mnemonicPhrase: string;
}

export const MnemonicPhrase = ({
  mnemonicPhrase = "",
}: MnemonicPhraseProps) => {
  const [isConfirmed, setIsConfirmed] = useState(false);
    return isConfirmed ? (
      <>
        <Header />
        <FullscreenStyle />
        <Onboarding customBackAction={() => setIsConfirmed(false)} hasGoBackBtn>
          <ConfirmMnemonicPhrase words={shuffle(mnemonicPhrase.split(" "))} />
        </Onboarding>
      </>
    ) : (
      <>
        <Header />
        <FullscreenStyle />
        <Onboarding>
          <DisplayMnemonicPhrase
            mnemonicPhrase={mnemonicPhrase}
            setIsConfirmed={setIsConfirmed}
          />
        </Onboarding>
      </>
        <MnemonicPhrase mnemonicPhrase={MNEMONIC} />
          <MnemonicPhrase mnemonicPhrase={MNEMONIC} />