Is Fast Wallet safe?

Medium risk

Fast Wallet sends biometric auth keys and a persistent device identifier to api.suiet.app, a third-party server, during biometric setup.

When a user enables, rotates, or disables biometric authentication, the extension transmits a persistent per-device client_id along with public keys and signatures to api.suiet.app — a server operated by Suiet, a separate wallet project. The extension also injects a crypto wallet API (window.fastset) into every webpage the user visits, exposing account access methods such as connect(), signMessage(), and transfer() to all page scripts. Additionally, wallet account addresses and public keys are broadcast via postMessage with a wildcard origin ('*'), making them readable by any frame on the page.

Fastv1.0.17Chrome Web Store
45Risk
Who publishes it

Fast - no other listings under this identity, 3 shared hostnames

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Fast
Registered address
3508 Cypress Creek Road, Champaign, IL 61822, US
Registered contact
Musab Ahmad Alturki

Shared hosts - 3 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

api.suiet.app
Also called by 1 other listing: Suiet
blog.plover.com
Also called by 2 other listings, including FlowCrypt: Encrypt Gmail with PGP
explorer.sui.io
Also called by 2 other listings, including Energy8 Wallet

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Biometric auth posts device key data to api.suiet.app

Touch ID setup, rotation, or disable posts biometric-auth records to api.suiet.app with a persistent chrome-prefixed client ID.

Setup/rotation also send public-key material and an auth key.

Source-code evidence; DA captured no request.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You change or use the wallet's Touch ID authentication flow.

The source paths cover setup, auth-key rotation during biometric unlock, and disable.

The extension did this

The extension prepares a POST to api.suiet.app with the device client ID.

Setup and rotation also include public-key material and a generated auth key.

Fields the source code places in biometric-auth requests
  • Device client ID
    chrome-q4k8x7m2n5p9r3t6v1s0

    Lets the remote auth service tie biometric-auth requests to the same browser profile over time.

  • Generated auth key
    v7ny8t2q0k5abc9m4x1r6zps

    Part of the wallet's Touch ID unlock flow is sent to the remote auth service during setup and rotation.

  • Biometric public key
    pQECAyYgASFYILhO5yVf2j7fX8qfU8G0QnPGk0kQAcW6mXWgpjOjoH0VIlggx9K2m5Wl1jM8TnZP6Qf4GkK7a0F3rB9pV2sH6cD1eA4=

    Connects the browser profile to the public-key credential created for Touch ID.

  • Signed challenge
    eyJtZXNzYWdlIjoiRmFzdCBXYWxsZXQiLCJkYXRldGltZSI6IjIwMjYtMDctMTJUMjI6NTA6MzUuNDk0WiIsIm5vbmNlIjo2ODQyMTkzN30=

    Shows a Touch ID unlock attempt and links that attempt back to the same device client ID.

Captured request
POSThttps://api.suiet.app/extension/auth/set-auth-key

The source code issues this POST during Touch ID setup and token-change handling; no request body was recorded during dynamic analysis.

Headers
content-type
application/json
Captured request
POSThttps://api.suiet.app/extension/auth/rotate-auth-key

The source code issues this POST during biometric unlock key rotation; no request body was recorded during dynamic analysis.

Headers
content-type
application/json
Captured request
POSThttps://api.suiet.app/extension/auth/delete-auth-key

The source code issues this POST when Touch ID is disabled; no request body was recorded during dynamic analysis.

Headers
content-type
application/json
The code that does this

Biometric-auth code paths in the shipped bundle

Readable version

Persistent chrome- client ID

assets/auth-DxF_k_Sy.js
async getClientId() {  const meta = await this.storage.loadMeta();  if (!meta) {    throw new MetadataMissingError();  }  if (!meta.clientId) {    meta.clientId = generateClientId(20, void 0, "chrome-");    await this.storage.saveMeta(meta);  }  return meta.clientId;}

Touch ID setup POST

assets/auth-DxF_k_Sy.js
async biometricAuthEnable({  credentialIdBase64,  publicKeyBase64}) {  const meta = await this.storage.loadMeta();  if (!meta) {    throw new MetadataMissingError();  }  const token = this.getToken();  const clientId = await this.getClientId();  const authKey = generateClientId(24);  const encryptedToken = encryptString(bufferExports.Buffer.from(authKey), token);  try {    const resp = await fetch(      `https://api.suiet.app/extension/auth/set-auth-key`,      {        method: "POST",        headers: {          "content-type": "application/json"        },        body: JSON.stringify({          client_id: clientId,          auth_key: authKey,          public_key_base64: publicKeyBase64        })      }    );    if (resp.ok) {      meta.biometricData = {        credentialIdBase64,        publicKeyBase64,        encryptedToken      };      await this.storage.saveMeta(meta);      return true;    }  } catch (e) {  }  return false;}

Touch ID key rotation POST

assets/auth-DxF_k_Sy.js
async biometricAuthRotateAuthKey({  challengeBase64,  signatureBase64}) {  const meta = await this.storage.loadMeta();  if (!meta) {    throw new MetadataMissingError();  }  if (!meta.biometricData) {    throw new Error("Biometric authentication not enabled");  }  const clientId = await this.getClientId();  const newAuthKey = generateClientId(24);  let shouldClear = false;  try {    const resp = await fetch(      `https://api.suiet.app/extension/auth/rotate-auth-key`,      {        method: "POST",        headers: {          "content-type": "application/json"        },        body: JSON.stringify({          client_id: clientId,          message_base64: challengeBase64,          signature_base64: signatureBase64,          public_key_base64: meta.biometricData.publicKeyBase64,          auth_key: newAuthKey        })      }    );    if (resp.ok) {      const { auth_key: authKey } = await resp.json();      if (authKey) {        try {          await this.biometricAuthUnlockWithAuthKey(authKey, newAuthKey);          return true;        } catch (e) {          shouldClear = true;        }      }    } else {      try {        const { error_code: errorCode } = await resp.json();        if (errorCode === "NOT_FOUND") {          shouldClear = true;        }      } catch (e) {      }    }  } catch (e) {  }  try {    if (shouldClear) {      delete meta.biometricData;      await this.storage.clearMeta();      await this.storage.saveMeta(meta);    }  } catch (e) {  }  return false;}

Touch ID disable POST

assets/auth-DxF_k_Sy.js
async biometricAuthDisable() {  const meta = await this.storage.loadMeta();  if (!meta) {    throw new MetadataMissingError();  }  if (meta.biometricData) {    delete meta.biometricData;    await this.storage.clearMeta();    await this.storage.saveMeta(meta);    await fetch(`https://api.suiet.app/extension/auth/delete-auth-key`, {      method: "POST",      headers: {        "content-type": "application/json"      },      body: JSON.stringify({        client_id: await this.getClientId()      })    });  }}
Remote destination used by the biometric-auth flow
    • api.suiet.app

    Receives extension auth POSTs for Touch ID setup, auth-key rotation, token-change handling, and disable requests.

Where it sends data

Destinations our analysis observed Fast Wallet contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • api.suiet.app

    Fast Wallet sends data to api.suiet.app. No other extension we have analysed sends data here.

Updated 30 September 2026ghibjknldlhfffnckpencpcjbhefblbe