Metamask Snap Audit Report for The Warp

Management Summary

The Warp contacted Sayfer Security in order to perform penetration testing on their MetaMask Snap in April 2025.

Before assessing the above services, we held a kickoff meeting with The Warp technical team and received an overview of the system and the goals for this research

Over the research period of 2 weeks, we discovered 8 vulnerabilities in the system.

In conclusion, several fixes should be implemented following the report, but the system’s security posture is competent.

After a review by the Sayfer team, we certify that all the security issues mentioned in this report have been addressed by The Warp team.

Risk Methodology

At Sayfer, we are committed to delivering the highest quality penetration testing to our clients. That’s why we have implemented a comprehensive risk assessment model to evaluate the severity of our findings and provide our clients with the best possible recommendations for mitigation.

Our risk assessment model is based on two key factors: IMPACT and LIKELIHOOD. Impact refers to the potential harm that could result from an issue, such as financial loss, reputational damage, or a non-operational system. Likelihood refers to the probability that an issue will occur, taking into account factors such as the complexity of the attack and the number of potential attackers.

By combining these two factors, we can create a comprehensive understanding of the risk posed by a particular issue and provide our clients with a clear and actionable assessment of the severity of the issue. This approach allows us to prioritize our recommendations and ensure that our clients receive the best possible advice on how to protect their business.

Risk is defined as follows:

Vulnerabilities by Risk

High – Direct threat to key business processes.
Medium – Indirect threat to key business processes or partial threat to business processes.
Low – No direct threat exists. The vulnerability may be exploited using other vulnerabilities.
Informational – This finding does not indicate vulnerability, but states a comment that notifies about design flaws and improper implementation that might cause a problem in the long run.

Severity
# of issues
Low
2
Medium
2
High
0
Informational
4

Approach

Introduction

The Warp contacted Sayfer to perform penetration testing on their MetaMask Snap application.

This report documents the research carried out by Sayfer targeting the selected resources defined under the research scope. Particularly, this report displays the security posture review for The Warp’s MetaMask Snap application and its surrounding infrastructure and process implementations.

 

Our penetration testing project life cycle:

01

Scope Overview

02

Technical Overview

03

Scope Validation

04

Threat Model

05

Security Evaluation

06

Security Assessment

Scope Overview

During our first meeting and after understanding the company’s needs, we defined the application’s scope that resides at the following URLs as the scope of the project:

  • The Warp’s MetaMask Snap
    • Audit commit: f41db7f97c5dd3f4f16288b46e67cf0b77a5a00d
    • Fixes commit: 8af590c817bb567ecd1c4b6ecb3ae4a74d1eca76

Our tests were performed from 16/04/2025 to 30/04/2025.

Don’t let it be too late!

Start your audit with Sayfer

Scope Validation

We began by ensuring that the scope defined to us by the client was technically logical.

Deciding what scope is right for a given system is part of the initial discussion. Getting the scope right is key to deriving maximum business value from the research.

Threat Model

During our kickoff meetings with the client we defined the most important assets the application possesses.
We defined that the largest current threat to the system is the possibility of malicious actors hijacking the user’s account.

Don’t let it be too late!

Start your audit with Sayfer

Security Evaluation Methodology

Sayfer uses OWASP WSTG as our technical standard when reviewing web applications. After gaining a thorough understanding of the system we decided which OWASP tests are required to evaluate the system.

Security Assessment

After understanding and defining the scope, performing threat modeling, and evaluating the correct tests required in order to fully check the application for security flaws, we performed our security assessment.

Issue Table Description

Issue title

ID SAY-??: An ID for easy communication on each vulnerability
Status Open/Fixed/Acknowledged
Risk Represents the risk factor of the issue. For further description refer to the Vulnerabilities by Risk section.
Business Impact The main risk of the vulnerability at a business level.
Location The URL or the file in which this issue was detected. Issues with no location have no particular location and refer to the product as a whole.

Description

Here we provide a brief description of the issue and how it formed, the steps we made to find or exploit it, along with proof of concept (if present), and how this issue can affect the product or its users.

Mitigation

Suggested resolving options for this issue and links to advised sites for further remediation.

Security Evaluation

The following tests were conducted while auditing the system

Information Gathering

Information Gathering Test Name Status
WSTG-INFO-01 Conduct Search Engine Discovery Reconnaissance for Information Leakage Pass
WSTG-INFO-02 Fingerprint Web Server Pass
WSTG-INFO-03 Review Webserver Metafiles for Information Leakage Pass
WSTG-INFO-04 Enumerate Applications on Webserver Pass
WSTG-INFO-05 Review Webpage Content for Information Leakage Pass
WSTG-INFO-06 Identify application entry points Pass
WSTG-INFO-07 Map execution paths through application Pass
WSTG-INFO-08 Fingerprint Web Application Framework Pass
WSTG-INFO-09 Fingerprint Web Application Pass
WSTG-INFO-10 Map Application Architecture Pass

Configuration and Deploy Management Testing

Configuration and Deploy Management Testing Test Name Status
WSTG-CONF-01 Test Network Infrastructure Configuration Pass
WSTG-CONF-02 Test Application Platform Configuration Pass
WSTG-CONF-03 Test File Extensions Handling for Sensitive Information Pass
WSTG-CONF-04 Review Old Backup and Unreferenced Files for Sensitive Information Pass
WSTG-CONF-05 Enumerate Infrastructure and Application Admin Interfaces Pass
WSTG-CONF-06 Test HTTP Methods Pass
WSTG-CONF-07 Test HTTP Strict Transport Security Pass
WSTG-CONF-08 Test RIA cross domain policy Pass
WSTG-CONF-09 Test File Permission Pass
WSTG-CONF-10 Test for Subdomain Takeover Pass
WSTG-CONF-11 Test Cloud Storage Pass

Identity Management Testing

Identity Management Testing Test Name Status
WSTG-IDNT-01 Test Role Definitions Pass
WSTG-IDNT-02 Test User Registration Process Pass
WSTG-IDNT-03 Test Account Provisioning Process Pass
WSTG-IDNT-04 Testing for Account Enumeration and Guessable User Account Pass
WSTG-IDNT-05 Testing for Weak or unenforced username policy Pass

Authentication Testing

Authentication Testing Test Name Status
WSTG-ATHN-01 Testing for Credentials Transported over an Encrypted Channel Pass
WSTG-ATHN-02 Testing for Default Credentials Pass
WSTG-ATHN-03 Testing for Weak Lock Out Mechanism Pass
WSTG-ATHN-04 Testing for Bypassing Authentication Schema Pass
WSTG-ATHN-05 Testing for Vulnerable Remember Password Pass
WSTG-ATHN-06 Testing for Browser Cache Weaknesses Pass
WSTG-ATHN-07 Testing for Weak Password Policy Pass
WSTG-ATHN-08 Testing for Weak Security Question Answer Pass
WSTG-ATHN-09 Testing for Weak Password Change or Reset Functionalities Pass
WSTG-ATHN-10 Testing for Weaker Authentication in Alternative Channel Pass

Authorization Testing

Authorization Testing Test Name Status
WSTG-ATHZ-01 Testing Directory Traversal File Include Pass
WSTG-ATHZ-02 Testing for Bypassing Authorization Schema Pass
WSTG-ATHZ-03 Testing for Privilege Escalation Pass
WSTG-ATHZ-04 Testing for Insecure Direct Object References Pass

Session Management Testing

Session Management Testing Test Name Status
WSTG-SESS-01 Testing for Session Management Schema Pass
WSTG-SESS-02 Testing for Cookies Attributes Pass
WSTG-SESS-03 Testing for Session Fixation Pass
WSTG-SESS-04 Testing for Exposed Session Variables Pass
WSTG-SESS-05 Testing for Cross Site Request Forgery Pass
WSTG-SESS-06 Testing for Logout Functionality Pass
WSTG-SESS-07 Testing Session Timeout Pass
WSTG-SESS-08 Testing for Session Puzzling Pass
WSTG-SESS-09 Testing for Session Hijacking Pass

Data Validation Testing

Data Validation Testing Test Name Status
WSTG-INPV-01 Testing for Reflected Cross Site Scripting Pass
WSTG-INPV-02 Testing for Stored Cross Site Scripting Pass
WSTG-INPV-03 Testing for HTTP Verb Tampering Pass
WSTG-INPV-04 Testing for HTTP Parameter Pollution Pass
WSTG-INPV-05 Testing for SQL Injection Pass
WSTG-INPV-06 Testing for LDAP Injection Pass
WSTG-INPV-07 Testing for XML Injection Pass
WSTG-INPV-08 Testing for SSI Injection Pass
WSTG-INPV-09 Testing for XPath Injection Pass
WSTG-INPV-10 Testing for IMAP SMTP Injection Pass
WSTG-INPV-11 Testing for Code Injection Pass
WSTG-INPV-12 Testing for Command Injection Pass
WSTG-INPV-13 Testing for Format String Injection Pass
WSTG-INPV-14 Testing for Incubated Vulnerability Pass
WSTG-INPV-15 Testing for HTTP Splitting Smuggling Pass
WSTG-INPV-16 Testing for HTTP Incoming Requests Pass
WSTG-INPV-17 Testing for Host Header Injection Pass
WSTG-INPV-18 Testing for Server-side Template Injection Pass
WSTG-INPV-19 Testing for Server-Side Request Forgery Pass

Error Handling

Error Handling Test Name Status
WSTG-ERRH-01 Testing for Improper Error Handling Pass
WSTG-ERRH-02 Testing for Stack Traces Pass

Cryptography

Cryptography Test Name Status
WSTG-CRYP-01 Testing for Weak Transport Layer Security Pass
WSTG-CRYP-02 Testing for Padding Oracle Pass
WSTG-CRYP-03 Testing for Sensitive Information Sent via Unencrypted Channels Pass
WSTG-CRYP-04 Testing for Weak Encryption Pass

Business logic Testing

Business logic Testing Test Name Status
WSTG-BUSL-01 Test Business Logic Data Validation Pass
WSTG-BUSL-02 Test Ability to Forge Requests Pass
WSTG-BUSL-03 Test Integrity Checks Pass
WSTG-BUSL-04 Test for Process Timing Pass
WSTG-BUSL-05 Test Number of Times a Function Can be Used Limits Pass
WSTG-BUSL-06 Testing for the Circumvention of Work Flows Pass
WSTG-BUSL-07 Test Defenses Against Application Mis-use Pass
WSTG-BUSL-08 Test Upload of Unexpected File Types Pass
WSTG-BUSL-09 Test Upload of Malicious Files Pass

Client Side Testing

Client Side Testing Test Name Status
WSTG-CLNT-01 Testing for DOM-Based Cross Site Scripting Pass
WSTG-CLNT-02 Testing for JavaScript Execution Pass
WSTG-CLNT-03 Testing for HTML Injection Pass
WSTG-CLNT-04 Testing for Client Side URL Redirect Pass
WSTG-CLNT-05 Testing for CSS Injection Pass
WSTG-CLNT-06 Testing for Client Side Resource Manipulation Pass
WSTG-CLNT-07 Test Cross Origin Resource Sharing Pass
WSTG-CLNT-08 Testing for Cross Site Flashing Pass
WSTG-CLNT-09 Testing for Clickjacking Pass
WSTG-CLNT-10 Testing WebSockets Pass
WSTG-CLNT-11 Test Web Messaging Pass
WSTG-CLNT-12 Testing Browser Storage Pass
WSTG-CLNT-13 Testing for Cross Site Script Inclusion Pass

API Testing

API Testing Test Name Status
WSTG-APIT-01 Testing GraphQL Pass

Order audit from Sayfer

    This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

    Security Assessment Findings

    Missing User Confirmation When Switching Active Wallets

    ID SAY-01
    Status Fixed
    Risk Medium
    Business Impact A malicious dApp can invoke xrpl_switchWallet and silently swap the active signer without user approval, enabling transactions under a wallet the user did not intend to activate.
    Location – src/handler/account/SwitchWalletHandler.ts;
    SwitchWalletHandler.handle(string, {string})

    Description

    The handler loads the imported wallet immediately, without prompting the user via any dialog. As a result, any downstream sign or signAndSubmit operations will use the new wallet without explicit user consent.

    • SwitchWalletHandler.ts:13-22
    // If switching to derived wallet
    if (params.address this.context.derivedWallet.address) {
     // Update context
     await this.context.updateActiveWallet(undefned);
     Update state
     await this.context.stateManager.set({
      activeImportedWallet: undefned,
     });
     return { address: params.address };
    }

    Mitigation

    We recommend presenting the user with a confirmation dialog before calling updateActiveWallet(string?).

     

    Entropy Hex Treated as ASCII in Encryption/Decryption

    ID SAY-02
    Status Fixed
    Risk Medium
    Business Impact Treating the hex-encoded entropy string as UTF-8 reduces effective key entropy by a factor of 4, weakening PBKDF2-derived keys and making seed encryption more vulnerable to brute-force attacks.
    Location – src/core/utils/encryption.ts;
    – EncryptionManager.encryptData(string)
    – EncryptionManager.decryptData(string)

    Description

    The code calls TextEncoder().encode(entropy) where entropy is a hex string (e.g. “1a2b3c…”) instead of converting it to raw bytes. This reduces the entropy drastically.

    • encryption.ts:20-27, 94-101
    const encoder = new TextEncoder();
    const keyMaterial = await crypto.subtle.importKey(
     'raw',
     encoder.encode(entropy),
     { name: 'PBKDF2' },
     false,
     ['deriveKey']
    );

    Mitigation

    We recommend hex-decoding the entropy into a Uint8Array before importing the key.

     

    State Update during the Read-Only Endpoint Call

    ID SAY-03
    Status Fixed
    Risk Low
    Business Impact Every ListWallets request writes to state (updating derivedWalletAddress), causing unintended side‐effects and unexpected extra storage writes
    Location – src/handler/account/ListWalletsHandler.ts;
    ListWalletsHandler.handle()

    Description

    In ListWalletsHandler, the logic is meant to be a pure “get” but performs a set operation whenever the derived address differs.

    • ListWalletsHandler.ts:28-30
    // Ensure the derived wallet address is stored in state for future
    rehydration
    if (!state.derivedWalletAddress state.derivedWalletAddress
    derivedWallet.address) {
     await this.context.stateManager.set({ derivedWalletAddress:
    derivedWallet.address });
    }

    Mitigation

    We recommend reconsidering the one‐time derived‐address write to initialization (Context.init()), and removing state writes from the handle() method so it remains truly read-only.

     

    Redundant State Write

    ID SAY-04
    Status Fixed
    Risk Low
    Business Impact This finding constitutes a minor performance inefficiency.
    Location – src/handler/account/SwitchWalletHandler.ts;
    SwitchWalletHandler.handle(string, {string})

    Description

    In SwitchWalletHandler, the call to updateActiveWallet(string?) already clears activeImportedWallet in state, yet the code immediately calls stateManager.set(Partial) again.

    • SwitchWalletHandler.ts:13-22
    //If switching to derived wallet
    if (params.address this.context.derivedWallet.address) {
     //Update context
     await this.context.updateActiveWallet(undefned);
     //Update state
     await this.context.stateManager.set({
      activeImportedWallet: undefned,
     });
     return { address: params.address };
    }

    Mitigation

    We recommend eliminating the second stateManager.set(Partial<State>) call and rely solely on updateActiveWallet(string?).

     

    Incorrect Regex

    ID SAY-05
    Status Fixed
    Risk Low
    Business Impact The pattern /^00|s/ strips any “s” in the key, not only at the start. While hex cannot contain such a character (and therefore the severity of this finding was rated informational), fixing this is recommended.
    Location – src/core/Wallet.ts; Wallet.fromPrivateKey(string)

    Description

    The code intends to remove a leading “00” or “s” prefix, but the ungrouped alternation matches either “^00” or any “s” globally.

    • Wallet.ts:73
    const cleanPrivateKey = privateKey.replace(/^00|s/, '').toUpperCase();

    Mitigation

    We recommend using a grouped, anchored regex to strip only the prefix.

    const cleanPrivateKey = privateKey.replace(/^(?:00|s)/, '').toUpperCase();

     

    Redundant Try/Catch in Encryption Methods

    ID SAY-06
    Status Acknowledged
    Risk Informational
    Business Impact This finding is purely informational.
    Location – src/core/utils/encryption.ts;
    – EncryptionManager.encryptData(string)
    – EncryptionManager.decryptData(string)

    Description

    Both encryptData(string) and decryptData(string) wrap their entire logic in a try/catch block, which simply throws the error without any additional handling.

    Mitigation

    Remove the outer try/catch blocks and let promise rejections propagate naturally.

     

    Redundant Null Check

    ID SAY-07
    Status Acknowledged
    Risk Informational
    Business Impact This finding is purely informational.
    Location – src/handler/account/ImportWalletHandler.ts;
    ImportWalletHandler.handle(string, {string?, string?})

    Description

    In ImportWalletHandler, after verifying if (!params.seed && !params.privateKey), the code does a second if (!seed) check, which can never be true.

    • ImportWalletHandler.ts:15-23
    if (!params.seed !params.privateKey) {
     throw new InvalidParamsError('Family seed must be provided');
    }
    // Convert privateKey parameter to seed if provided
    const seed = params.seed params.privateKey;
    if (!seed) {
     throw new InvalidParamsError('Family seed must be provided');
    }

    Mitigation

    We recommend removing the second if block to streamline the logic.

     

    Unused Parameter

    ID SAY-08
    Status Acknowledged
    Risk Informational
    Business Impact This finding is purely informational.
    Location – src/handler/account/SwitchWalletHandler.ts;
    SwitchWalletHandler.handle(string, {string})

    Description

    SwitchWalletHandler.handle(string, {string}) takes an origin argument but never references it again.

    Mitigation

    Consider removing this parameter if it is not necessary.

    You can find more information about it on our Blog

    Sayfer’s blog focuses on web3, security, and vulnerability research. We believe that in the cybersecurity industry it’s crucial to stay up to date on the latest trends and advancements. Currently, our team of experienced researchers enjoys researching cutting-edge blockchain and web3 technologies.
    Contact us

    Keep In Touch

    Location
    Tel Aviv, Israel
    Messengers:
    Please feel free to contact us, we will be happy to respond!

      This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
      Skip to content