Adena Wallet Chrome Extension - OnBloc


Prepared by:

Halborn Logo

HALBORN

Last Updated 03/11/2025

Date of Engagement: January 14th, 2025 - January 27th, 2025

Summary

100% of all REPORTED Findings have been addressed

All findings

13

Critical

0

High

2

Medium

8

Low

3

Informational

0


1. Introduction

Onbloc engaged Halborn to conduct a security assessment on the Adena Wallet browser extension, beginning on January 14th, 2025 and ending on January 27th, 2025. The security assessment was scoped to the current extension itself, version v1.14.0. The client team provided the source code to allow the security engineers to conduct testing using tools for scanning, detecting, and validating possible vulnerabilities, and report the findings during the engagement.

2. Assessment Summary

The team at Halborn was provided two weeks for the engagement and assigned a full-time security engineer to verify the security of the browser extension. The engineer has advanced knowledge in penetration testing, red teaming, and multiple blockchain protocols.

The goals of our security assessments are as follows:

    • Improve the security of the implementation

    • Identify potential security issues affecting components interacting with the extension


The wallet exposes the mnemonic phrase in memory, where the mnemonic phrase remains unencrypted in memory even after the wallet is locked, possibly allowing attackers with access to the user's machine to exfiltrate it. Additionally, the user's password was also found stored in cleartext in memory. Furthermore, the wallet uses a static encryption key to encrypt a dynamically generated UUID, which is then used to encrypt the wallet password.

The wallet has several medium-severity vulnerabilities, being two of the most important ones, sensitive data such as mnemonic phrases and private keys possibly being exposed due to the clipboard copy feature, and the wallet also lacks an auto-locking feature, leaving sessions vulnerable to unauthorized access.

Dependencies are not pinned to exact versions, allowing for potential dependency attacks, although they are set to supported ranges. GraphQL introspection queries are enabled, exposing the API schema and backend structure, which could be leveraged to craft malicious queries or access sensitive data. Additionally, the wallet configuration can be overwritten by directly accessing the registration page, compromising the wallet’s integrity and allowing unauthorized changes to the setup.

It is recommended to resolve all the security issues listed in the document to improve the security health of the application and its underlying infrastructure.

3. Test Approach and Methodology

Halborn followed both a whitebox and blackbox approach as per the scope and performed a combination of both manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy regarding the scope of the pentest. While manual testing is recommended to uncover flaws in logic, process and implementation; automated testing techniques assist enhance coverage of the infrastructure and can quickly identify flaws in it.

The assessment methodology covered a range of phases of tests, and employed various tools, including but not limited to the following:

    • Verify minimum necessary permissions

    • Source code review

    • Hardcoded credentials or API keys

    • Sensitive data leakage

    • Robust Content Security Policy (CSP)

    • Manifest file configuration review

    • Validate and sanitize user inputs

    • Ensure sensitive data secure storage

    • Secure communications for all network communication

    • Security headers configuration

    • Ensure the least privileges for scripts

    • Component isolation verification

    • Third-party libraries review

    • Monitor extension behavior

    • Event listeners and handlers review

    • Data collection practices verification

    • Multiple browsers verification

    • Regulatory compliance

    • Static code analysis

    • Dynamic analysis

    • Review documentation completeness

    • Error handling

    • Rate limiting

4. RISK METHODOLOGY

Vulnerabilities or issues observed by Halborn are ranked based on the risk assessment methodology by measuring the LIKELIHOOD of a security incident and the IMPACT should an incident occur. This framework works for communicating the characteristics and impacts of technology vulnerabilities. The quantitative model ensures repeatable and accurate measurement while enabling users to see the underlying vulnerability characteristics that were used to generate the Risk scores. For every vulnerability, a risk level will be calculated on a scale of 5 to 1 with 5 being the highest likelihood or impact.
RISK SCALE - LIKELIHOOD
  • 5 - Almost certain an incident will occur.
  • 4 - High probability of an incident occurring.
  • 3 - Potential of a security incident in the long term.
  • 2 - Low probability of an incident occurring.
  • 1 - Very unlikely issue will cause an incident.
RISK SCALE - IMPACT
  • 5 - May cause devastating and unrecoverable impact or loss.
  • 4 - May cause a significant level of impact or loss.
  • 3 - May cause a partial impact or loss to many.
  • 2 - May cause temporary impact or loss.
  • 1 - May cause minimal or un-noticeable impact.
The risk level is then calculated using a sum of these two values, creating a value of 10 to 1 with 10 being the highest level of security risk.
Critical
High
Medium
Low
Informational
  • 10 - CRITICAL
  • 9 - 8 - HIGH
  • 7 - 6 - MEDIUM
  • 5 - 4 - LOW
  • 3 - 1 - VERY LOW AND INFORMATIONAL

5. SCOPE

Files and Repository
(a) Repository: adena-wallet
(b) Assessed Commit ID: 38f089a
(c) Items in scope:
    Out-of-Scope:
    Remediation Commit ID:
    Out-of-Scope: New features/implementations after the remediation commit IDs.

    6. Assessment Summary & Findings Overview

    Critical

    0

    High

    2

    Medium

    8

    Low

    3

    Informational

    0

    Impact x Likelihood

    HAL-01

    HAL-02

    HAL-06

    HAL-13

    HAL-03

    HAL-04

    HAL-05

    HAL-08

    HAL-09

    HAL-10

    HAL-07

    HAL-11

    HAL-12

    Security analysisRisk levelRemediation Date
    MNEMONIC PHRASE EXPOSURE IN MEMORYHighSolved - 03/07/2025
    REUSE OF STATIC ENCRYPTION KEYHighSolved - 02/04/2025
    EVENT LISTENER ACCEPTS MESSAGES FROM ANY ORIGINMediumSolved - 02/04/2025
    MESSAGES SENT TO ANY ORIGINMediumSolved - 02/04/2025
    LACK OF BUSINESS LOGIC VALIDATIONMediumSolved - 02/05/2025
    VULNERABLE THIRD-PARTY DEPENDENCIESMediumSolved - 03/03/2025
    LACK OF RATE LIMITINGMediumSolved - 03/03/2025
    POTENTIAL RISK OF SENSITIVE DATA EXPOSURE THROUGH CLIPBOARDMediumSolved - 02/04/2025
    LACK OF WALLET AUTO-LOCKMediumSolved - 02/05/2025
    UNRESTRICTIVE CONTENT-SECURITY-POLICY (CSP)MediumRisk Accepted - 02/04/2025
    DEPENDENCIES SHOULD BE PINNED TO EXACT VERSIONSLowSolved - 02/04/2025
    GRAPHQL INTROSPECTION ENABLEDLowSolved - 03/03/2025
    WALLET CONFIGURATION OVERWRITE VIA DIRECT ACCESS TO THE REGISTER PAGELowSolved - 02/04/2025

    7. Findings & Tech Details

    7.1 MNEMONIC PHRASE EXPOSURE IN MEMORY

    //

    High

    Description

    The mnemonic phrase of the wallet is kept unencrypted in memory, even the wallet was locked. As a result, an attacker with access to the user’s machine could exfiltrate the mnemonic phrase. This makes the wallet web extension vulnerable to Demonic (CVE-2022-32969). The user password in cleartext was also found.

    It is important to recognize that the mnemonic risk extends beyond the application state; it could also be leaked into memory when the browser displays the mnemonic in clear text and as long as the process running.

    Proof of Concept

    Observe, for example, the following lines in https://github.com/onbloc/adena-wallet/blob/38f089a900311ec773a3c6c6ae5807ef6db2bebb/packages/adena-module/src/wallet/keyring/hd-wallet-keyring.ts:

    export class HDWalletKeyring implements Keyring {
      public readonly id: string;
      public readonly type: KeyringType = 'HD_WALLET';
      public readonly seed: Uint8Array;
      public readonly mnemonic: string;
    
      constructor({ id, mnemonic, seed }: KeyringData) {
        if (!mnemonic || !seed) {
          throw new Error('Invalid parameter values');
        }
        this.id = id || uuidv4();
        this.mnemonic = mnemonic;
        this.seed = Uint8Array.from(seed);
      }

    In this example, the mnemonic phrase may be maintained in cleart text in the memory.



    Observe, for example, the following lines in https://github.com/onbloc/adena-wallet/blob/38f089a900311ec773a3c6c6ae5807ef6db2bebb/packages/adena-extension/src/repositories/wallet/wallet.ts:

      public getWalletPassword = async (): Promise<string> => {
        const encryptedKey = await this.sessionStorage.get('ENCRYPTED_KEY');
        const encryptedPassword = await this.sessionStorage.get('ENCRYPTED_PASSWORD');
    
        if (encryptedKey === '' || encryptedPassword === '') {
          throw new WalletError('NOT_FOUND_PASSWORD');
        }
    
        try {
          const password = decryptPassword(encryptedKey, encryptedPassword);
          this.updateStoragePassword(password);
          return password;
        } catch (e) {
          throw new WalletError('NOT_FOUND_PASSWORD');
        }
      };

    In this example, the user password may be maintained in cleart text in the memory.



    In the following images, evidences of this situation can be seen when the wallet is in locked state:

    Demonic attack retrieving the mnemonic from memory, while the wallet is locked
    User password in cleartext in memory, while the wallet is locked
    Retrieving the mnemonic from memory, while the wallet is locked
    Score
    CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:L(8.4)
    Recommendation

    The identified vulnerability arises from the application's handling of sensitive data in plain text. To mitigate this, the team recommends the following strategies:

    - Opt for storing the entropy on disk rather than the mnemonic itself. When the mnemonic is necessary in the code, consider breaking it into multiple variables. Alternatively, obfuscate the original phrase and subsequently dereference the variable holding the original phrase.

    - For instances requiring mnemonic phrase handling, utilize the obfuscated variable with a function designed to reconstruct the original mnemonic phrase exactly at the point of need.

    - Ensure that when the wallet is in a locked state, the mnemonic phrase is completely cleared from memory.

    For the display and handling of the mnemonic phrase during wallet creation and when revealed to a logged-in user:

    - Display the mnemonic phrase using an HTML5 canvas. This technique helps prevent users from copying the phrase, reducing the risk of it being unintentionally stored in memory via the clipboard.

    - Limit the ability for users to copy the entire mnemonic from the extension. This approach is essential in minimizing the potential for the mnemonic to be accidentally leaked through the clipboard, thereby enhancing the security of the sensitive information.

    Implementing these recommendations would significantly enhance the security of mnemonic phrase handling, reducing the risks associated with its exposure or misuse.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash

    7.2 REUSE OF STATIC ENCRYPTION KEY

    //

    High

    Description

    The use of a hardcoded static encryption key to encrypt a dynamically generated UUID, which is then used to encrypt the wallet password, has been detected.

    Proof of Concept
    import CryptoJS from 'crypto-js';
    import { v4 as uuidv4 } from 'uuid';
    
    // Static cipher key used for encrypting the cryptographic key
    const ENCRYPT_CIPHER_KEY = 'r3v4';
    
    export const encryptSha256Password = (password: string): string => {
      return CryptoJS.SHA256(password).toString();
    };
    
    // Encrypts a password with a dynamically generated key and returns the encrypted key and password
    export const encryptPassword = (
      password: string,
    ): { encryptedKey: string; encryptedPassword: string } => {
      const cryptKey = uuidv4();
      const adenaKey = ENCRYPT_CIPHER_KEY;
      const encryptedKey = CryptoJS.AES.encrypt(cryptKey, adenaKey).toString();
      const encryptedPassword = CryptoJS.AES.encrypt(password, cryptKey).toString();
      return {
        encryptedKey,
        encryptedPassword,
      };
    };
    
    // Decrypts a password using the encrypted key and password
    export const decryptPassword = (encryptedKey: string, encryptedPassword: string): string => {
      const adenaKey = ENCRYPT_CIPHER_KEY;
      const key = CryptoJS.AES.decrypt(encryptedKey, adenaKey).toString(CryptoJS.enc.Utf8);
      if (key === '') {
        throw new Error('CipherKey Decryption Failed');
      }
      const password = CryptoJS.AES.decrypt(encryptedPassword, key).toString(CryptoJS.enc.Utf8);
      if (password === '') {
        throw new Error('Password Decryption Failed');
      }
      return password;
    };

    The constant key (r3v4) used to encrypt the dynamically generated UUID is hardcoded. Anyone with access to the source code (which is public) can obtain the cipher key that allows to decrypt the UUID. The encrypted password and encrypted key is then stored in the web extension session storage. If a malicious actor is able to access the session storage of the web extension, they can retrieve both the encrypted password and the encrypted key. With the static cipher key r3v4, they can decrypt the UUID and then use that to decrypt the password, ultimately gaining access to the user's wallet password in plaintext:

    Decrypting the user password

    Additionally, using a UUID as the key for AES encryption is not cryptographically secure. While UUIDs are unique, they are not generated with cryptographic secure randomness. A better practice would be to use a secure random key generation method (e.g., using the Web Crypto API's crypto.getRandomValues()) for cryptographic keys.

    Score
    CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H(7.5)
    Recommendation

    Avoid static keys when possible. Storing sensitive data like keys or passwords in session storage is risky, using only in-memory storage can be considered. Also consider using a stronger encryption scheme, such as AES-GCM, instead of AES-CBC (the default for CryptoJS.AES).

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    5a20b3900f9d5d2637e465f0006faab7f2d99171

    7.3 EVENT LISTENER ACCEPTS MESSAGES FROM ANY ORIGIN

    //

    Medium

    Description

    Accepting events from any origin in an event listener can lead to security vulnerabilities such as unauthorized actions, event spoofing, and exposure to malicious websites, possibly compromising the integrity of sensitive operations.

    Proof of Concept

    Observe the following lines in https://github.com/onbloc/adena-wallet/blob/38f089a900311ec773a3c6c6ae5807ef6db2bebb/packages/adena-extension/src/content.ts, where an event listener is initialized without any checks to the origin of the events:

    const initListener = (): void => {
      window.addEventListener(
        'message',
        (event) => {
          try {
            if (event.data?.status === 'request') {
              sendMessage(event);
            } else {
              return event.data;
            }
          } catch (e) {
            console.error(e);
          }
        },
        false,
      );
    };

    This event listener accepts events from any source, as the Content script is injected on every URL as the Manifest establish:

      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["content.js"]
        }
      ],
    Score
    CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N(6.5)
    Recommendation

    Restrict the sources that can send events to the event listener in the Content script, if possible. Note that this behaviour may be intended.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    a6b3f9e75df0ababe426e20f5f72571f71ecddde

    7.4 MESSAGES SENT TO ANY ORIGIN

    //

    Medium

    Description

    Using window.postMessage(this.eventMessage, '*') in a crypto wallet extension can be a security risk, as it allows messages to be sent to any origin, potentially exposing sensitive data to malicious actors or untrusted domains.

    Proof of Concept

    Observe the following lines in https://github.com/onbloc/adena-wallet/blob/38f089a900311ec773a3c6c6ae5807ef6db2bebb/packages/adena-extension/src/inject/executor/executor.ts, the messages are sent to any origin:

      private sendEventMessage = <T = unknown>(
        eventMessage: InjectionMessage,
      ): Promise<WalletResponse<T>> => {
        this.listen();
        this.eventMessage = {
          ...eventMessage,
          protocol: window.location.protocol,
          hostname: window.location.hostname,
          key: this.eventKey,
        };
        window.postMessage(this.eventMessage, '*');
        this.messages[this.eventKey] = {
          request: this.eventMessage,
          response: undefined,
        };
    Score
    CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N(6.5)
    Recommendation

    To prevent sensitive data from being exposed to untrusted sources, trusted origins can be specified in window.postMessage instead of using '*'. Note that this behavior may be intended.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    a71efaff7a6b3b7594b9f7db7aee7a1a9beb131a

    7.5 LACK OF BUSINESS LOGIC VALIDATION

    //

    Medium

    Description

    It was possible to add bogus or malicious tokens to the user’s balance by manipulating the server response.

    The wallet allowed users to add tokens either manually or by searching through a list of supported tokens. Although manual addition of malicious tokens was prevented due to input validation checks, the vulnerability lies in the handling of server responses for the supported token list.

    By intercepting and modifying the server response to a POST request sent to https://test5.api.onbloc.xyz/v1/gno (triggered during the "Search" functionality under "Add Custom Token" menus), it was possible to inject and display unsupported or malicious tokens in the token search results. These tokens could then be selected and added by the user, bypassing the application’s intended validation mechanisms and business logic.

    Impact

    This vulnerability breaks the integrity of the business logic and execution workflows within the wallet, leading to unintended or unexpected behaviors. Specifically:

    • Workflow Disruption: The wallet’s logic is designed to prevent the addition of unsupported or malicious tokens. Manipulating the server response allows bypassing this workflow, rendering the wallet’s security checks ineffective.

    • Integrity Violations: The application operates on the assumption that only validated tokens can be added by users. By injecting malicious or bogus tokens, attackers can compromise this assumption, potentially destabilizing dependent operations like balance calculations or token transfers.

    • Application Misbehavior: Fraudulent tokens with improper metadata (e.g., invalid contract addresses or incompatible formats) may lead to application crashes, errors, or undefined behaviors during transactions or token management processes.

    • Unintended Data States: The wallet may process data in unintended ways, such as incorrect balance updates or failed transactions, due to the introduction of unsupported tokens. This breaks the expected state of the application and creates potential confusion or mistrust among users.

    • Exploitation of Ecosystem Logic: These unintended behaviors could be further leveraged by attackers to exploit other components of the wallet or related systems (e.g., exploiting token-related vulnerabilities or breaking synchronization between the wallet and external services).

    By undermining the wallet's business logic, this vulnerability introduces systemic risks that compromise both the integrity and reliability of the application's core workflows.

    Proof of Concept

    From the “Manual” section of “Add Custom Token” menu was not possible to add a custom token that was not existing.

    However, if the server response was manipulated, it was possible to add custom tokens that were not actually existing, as the following picture shows.

    As an example, it was possible to manipulate with Match & Replace The proxy tool was configured with the next Match & Replace rules:

    • Match text:

    {"name":"Foo","owner":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","symbol":"FOO","packagePath":"gno.land/r/demo/foo20","decimals":4}

    • Replace:

    {"name":"Foo","owner":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","symbol":"FOO","packagePath":"gno.land/r/demo/foo20","decimals":4},{"name":"Hal","owner":"g17gprk6rymnnlayhfhx437xq7z48p26dxtux2k8","symbol":"HAL","packagePath":"bydp841zm2en4rcayczmsj063x9oxfl4.oastify.com","decimals":6,"packagePath":"gno.land/r/onbloc/foo"}

    The following request and responses were affected by the rules above.

    Request:
    POST /v1/gno HTTP/2
    Host: test5.api.onbloc.xyz
    Content-Length: 99
    Sec-Ch-Ua-Platform: "Windows"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
    Accept: application/json, text/plain, */*
    Sec-Ch-Ua: "Not A(Brand";v="8", "Chromium";v="132", "Google Chrome";v="132"
    Content-Type: application/json
    Sec-Ch-Ua-Mobile: ?0
    Origin:chrome-extension://pilbblmedmdhgjjomdopdlealdjminno
    Sec-Fetch-Site: cross-site
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Accept-Encoding: gzip, deflate, br
    Accept-Language: es-ES,es;q=0.9
    Priority: u=1, i
    
    {"id":"5b146960-d9bf-11ef-94d7-8b187d58a657","jsonrpc":"2.0","method":"getGRC20Tokens","params":[]}
    
    Response:
    • Original Response:

    HTTP/2 200 OK
    Date: Thu, 23 Jan 2025 19:22:18 GMT
    Content-Type: application/json
    Content-Length: 1476
    Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-AUTH-KEY, X-AUTH-DATA
    Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
    Access-Control-Allow-Origin: *
    Access-Control-Expose-Headers: X-AUTH-KEY, X-AUTH-DATA
    
    {"result":[{"name":"Foo","owner":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","symbol":"FOO","packagePath":"gno.land/r/demo/foo20","decimals":4},{"name":"Gnoswap","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"GNS","packagePath":"gno.land/r/gnoswap/v1/gns","decimals":6},{"name":"Usd Coin","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"USDC","packagePath":"gno.land/r/onbloc/usdc","decimals":6},{"name":"Foo","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"FOO","packagePath":"gno.land/r/onbloc/foo","decimals":6},{"name":"Bar","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAR","packagePath":"gno.land/r/onbloc/bar","decimals":6},{"name":"Baz","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAZ","packagePath":"gno.land/r/onbloc/baz","decimals":6},{"name":"Qux","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"QUX","packagePath":"gno.land/r/onbloc/qux","decimals":6},{"name":"Obl","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"OBL","packagePath":"gno.land/r/onbloc/obl","decimals":6},{"name":"Foo","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"FOO","packagePath":"gno.land/r/g1zh8w9tyl8y4hj374z5gckgknkfhuem67xxxm3m/foo","decimals":6},{"name":"Baz","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAZ","packagePath":"gno.land/r/g1zh8w9tyl8y4hj374z5gckgknkfhuem67xxxm3m/baz","decimals":6}],"jsonrpc":"2.0","id":"5b146960-d9bf-11ef-94d7-8b187d58a657"}
    

    • Auto-modified Response:

    HTTP/2 200 OK
    Date: Thu, 23 Jan 2025 19:22:18 GMT
    Content-Type: application/json
    Content-Length: 1669
    Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-AUTH-KEY, X-AUTH-DATA
    Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
    Access-Control-Allow-Origin: *
    Access-Control-Expose-Headers: X-AUTH-KEY, X-AUTH-DATA
    
    {"result":[{"name":"Foo","owner":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","symbol":"FOO","packagePath":"gno.land/r/demo/foo20","decimals":4},{"name":"Hal","owner":"g17gprk6rymnnlayhfhx437xq7z48p26dxtux2k8","symbol":"HAL","packagePath":"izlw9b26n9fu5ydhzj0ttq1d44avylma.oastify.com","decimals":6,"packagePath":"gno.land/r/onbloc/foo"},{"name":"Gnoswap","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"GNS","packagePath":"gno.land/r/gnoswap/v1/gns","decimals":6},{"name":"Usd Coin","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"USDC","packagePath":"gno.land/r/onbloc/usdc","decimals":6},{"name":"Foo","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"FOO","packagePath":"gno.land/r/onbloc/foo","decimals":6},{"name":"Bar","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAR","packagePath":"gno.land/r/onbloc/bar","decimals":6},{"name":"Baz","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAZ","packagePath":"gno.land/r/onbloc/baz","decimals":6},{"name":"Qux","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"QUX","packagePath":"gno.land/r/onbloc/qux","decimals":6},{"name":"Obl","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"OBL","packagePath":"gno.land/r/onbloc/obl","decimals":6},{"name":"Foo","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"FOO","packagePath":"gno.land/r/g1zh8w9tyl8y4hj374z5gckgknkfhuem67xxxm3m/foo","decimals":6},{"name":"Baz","owner":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","symbol":"BAZ","packagePath":"gno.land/r/g1zh8w9tyl8y4hj374z5gckgknkfhuem67xxxm3m/baz","decimals":6}],"jsonrpc":"2.0","id":"5b146960-d9bf-11ef-94d7-8b187d58a657"}
    

    That way, the Front-End of the wallet application started showing new bogus tokens to be added from the


    Other than that, it was possible to add tokens to the User's wallet with malicious Token Names and weird values for the Token Decimals, as shown in the following pictures:

    Score
    CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:L(5.6)
    Recommendation
    • Server-Side Validation: Ensure the server-side API validates all tokens that are about to be added to the user wallet, warrantying that the token features match the expected standards, like Token Decimals, Token Symbol length and characters allowed, etc...

    • Response Tamper Detection: Utilize cryptographic methods (e.g., digital signatures) to validate the integrity of server responses.

    • Log and Monitor: Log attempts to manipulate server responses and monitor unusual behavior for early detection of potential exploitation.

    • User Alerts: Warn users about the risks of adding tokens not verified by the wallet, and provide clear visual cues for unverified tokens.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    2638084db90297b23067ce5e02805f1692459a3d

    7.6 VULNERABLE THIRD-PARTY DEPENDENCIES

    //

    Medium

    Description

    The scoped repository uses multiple third-party dependencies. Using vulnerable third-party libraries can result in security vulnerabilities in the project that can be exploited by attackers. This can result in data breaches, theft of sensitive information, and other security issues. However, some of them were affected by public-known vulnerabilities that may pose a risk to the global application security level.

    Proof of Concept
    Score
    CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N(5.4)
    Recommendation

    Update all affected packages to its latest version.

    It is strongly recommended to perform an automated analysis of the dependencies from the birth of the project and if they contain any security issues. Developers should be aware of this and apply any necessary mitigation measures to protect the affected application.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    dfe10ab2d24cd277a1de75ec054ec27b940e54b1

    7.7 LACK OF RATE LIMITING

    //

    Medium

    Description

    API requests consume resources such as network, CPU, memory, and storage. This vulnerability occurs when too many requests arrive simultaneously, and the API does not have enough compute resources to handle those requests.


    During the assessment, no rate limitation policy was found on the API service. An attacker could exploit this vulnerability to overload the API by sending more requests than it can handle. As a result, the API becomes unavailable or unresponsive to new requests, or resources of bandwidth and CPU usage could be abused as well.

    Proof of Concept

    During the assessment, some example interesting endpoints where found allowing multiple parallel requests (POST HTTP request to https://test5.api.onbloc.xyz/v1/gno):

    Endpoint allowing multiple requests
    Score
    CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L(5.3)
    Recommendation

    This vulnerability is due to the application accepting requests from users at a given time without performing request throttling checks. It is recommended to follow the following best practices:

    • Implement a limit on how often a client can call the API within a defined timeframe.

    • Notify the client when the limit is exceeded by providing the limit number and the time the limit will be reset.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash

    7.8 POTENTIAL RISK OF SENSITIVE DATA EXPOSURE THROUGH CLIPBOARD

    //

    Medium

    Description

    The wallet application facilitates copying sensitive data, specifically mnemonic and private key passphrases, to the clipboard. This functionality presents a significant security risk, as clipboard data could be accessed both locally and remotely by unauthorized processes or malicious web pages. Attackers can exploit this vulnerability by leveraging scripts or pages designed to capture clipboard content, thereby compromising the confidentiality of critical information.

    Furthermore, in multi-device environments where clipboard sharing is enabled (such as between smartphones, tablets, and laptops), sensitive data copied to the clipboard can be inadvertently exposed across multiple devices. This significantly increases the attack surface, as an attacker gaining access to any linked device can retrieve the copied mnemonic or private key.

    Proof of Concept

    Look at the following example, in which the mnemonic phrase can be copied to the clipboard through the wallet:

    Allowing to copy mnemonic when creating a wallet
    Score
    CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N(4.8)
    Recommendation

    It is recommended to avoid providing a direct copy-to-clipboard feature for sensitive information, such as mnemonic and private key passphrases. Instead, consider implementing a secure display mechanism that requires users to manually input or write down the passphrase. If clipboard functionality is essential for user experience, implement automatic clipboard clearing after a short period to reduce exposure time. Additionally, display a warning when sensitive information is copied, advising users to clear their clipboard and avoid copying data in shared or multi-device environments where clipboard data can be synchronized across devices. Another option is to allow users to copy almost all the information necessary but not the complete secret, this way, the secret is not copied entirely to the clipboard. These measures will significantly reduce the risk of unauthorized access to sensitive information.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    3afc414b2a63ce9ddc72f53b5360fc6b31467b7c

    7.9 LACK OF WALLET AUTO-LOCK

    //

    Medium

    Description

    The wallet does not implement an auto-lock feature, allowing long access to the wallet without reauthentication, which can lead to unauthorized usage if the user leaves their session unattended.

    Proof of Concept

    The wallet does not seem to automatically lock itself after a period of inactivity, leaving it accessible indefinitely. This increases the risk of unauthorized access. After logging into the wallet, leaving the session idle does not trigger any auto-lock mechanism, allowing anyone with access to the device to interact with the wallet without re-authentication:

    Wallet not locked
    Score
    CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N(4.4)
    Recommendation

    Implement an auto-lock feature that locks the wallet after a predefined period of inactivity, requiring the user to re-authenticate before regaining access. This will prevent unauthorized access during unattended sessions.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    268ea08065206fae6808a995ca80f27ce23c04b2

    7.10 UNRESTRICTIVE CONTENT-SECURITY-POLICY (CSP)

    //

    Medium

    Description

    The wallet browser extension has a partially restrictive declared Content-Security-Policy (CSP) that could be improved to enhance security.

    Proof of Concept

    Observe the CSP declaration of the Adena Wallet web extension in https://github.com/onbloc/adena-wallet/blob/38f089a900311ec773a3c6c6ae5807ef6db2bebb/packages/adena-extension/public/manifest.json:

      "content_security_policy": {
        "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; img-src 'self' https: data:; font-src data:; style-src 'self' 'unsafe-inline'; connect-src 'self' data: https: http://127.0.0.1:*; frame-src https:;"
      }
    Score
    CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N(4.2)
    Recommendation

    The wallet browser extension fails to define a default-src directive, which acts as a fallback policy ensuring that no malicious resources are loaded from untrusted sources that have not been explicitly declared. The absence of this fallback increases the risk of loading unintended content from unauthorized origins.

    Additionally:

    • Remove unsafe-* keywords from the CSP declaration, unless absolutely necessary:

      • unsafe-inline

      • wasm-unsafe-eval

    • Limit http://127.0.0.1:* access in connect-src to specific trusted local ports or remove localhost access unless absolutely necessary.

    • Avoid data: URLs for img-src and font-src.

    • Restrict frame-src to trusted, known domains instead of broad https:.

    Remediation

    RISK ACCEPTED: The Onbloc team applied some measures to solve this finding. However, some unsafe-* keywords are still necessary due to the libsodium dependency.

    Remediation Hash
    23e877147700b53f4c8542b930eb2533b91593e1
    References

    7.11 DEPENDENCIES SHOULD BE PINNED TO EXACT VERSIONS

    //

    Low

    Description

    The application contained multiple dependencies that were not pinned to an exact version, but they were set to a supported version (ˆx.x.x). This could potentially allow dependency attacks.

    Proof of Concept

    Observe the versioning of the third-party dependencies of the packages in the repository adena-wallet:


    Dependencies of the adena-extension package:

      "dependencies": {
        "@adena-wallet/sdk": "^0.0.2",
        "@bufbuild/protobuf": "^2.2.3",
        "@gnolang/gno-js-client": "1.3.1",
        "@gnolang/tm2-js-client": "1.2.3",
        "@tanstack/react-query": "^4.36.1",
        "@vespaiach/axios-fetch-adapter": "^0.3.1",
        "adena-module": "*",
        "adena-torus-signin": "*",
        "axios": "0.27.2",
        "bignumber.js": "^9.1.2",
        "crypto-js": "^4.2.0",
        "dayjs": "^1.11.10",
        "html-loader": "^5.0.0",
        "lottie-web": "5.10.2",
        "node-polyfill-webpack-plugin": "^4.0.0",
        "qrcode.react": "^3.1.0",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "react-router-dom": "^6.22.1",
        "recoil": "^0.7.7",
        "styled-components": "^5.3.11",
        "uuidv4": "^6.2.13",
        "zxcvbn": "^4.4.2"
      }
    Score
    CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N(3.7)
    Recommendation

    The repository dependencies in the package.json files should be pinned to exact versions to prevent dependency attacks.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    SOLVED: the Onbloc team solved this vulnerability.

    7.12 GRAPHQL INTROSPECTION ENABLED

    //

    Low

    Description

    During the assessment, we discovered that GraphQL introspection was enabled, which exposes the API schema and structure. This information could be exploited by attackers to gain insights into your backend systems, craft malicious queries or mutations, and potentially access sensitive data or perform unintended actions.

    An attacker has complete insight of the backend queries and can further exploit these weaknesses, allowing them to run queries and mutations on the database without requiring administrative privileges. This chained attack significantly increases the potential impact and risk of unauthorized data access, data manipulation, and further exploitation of your application and infrastructure.

    Allowing introspection queries also possibly permits an attacker to launch several introspection queries in parallel possibly causing the server to consume a lot of resources and maybe leading into a Denial-of-Service.

    Proof of Concept

    In the following image, the GraphQL introspection query can be seen:

    GraphQL introspection query
    Score
    CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N(3.1)
    Recommendation

    It is recommended to make sure that there is no risk to the application and to mitigate the risks associated with GraphQL introspection in production environments, it is recommended the following actions:

    • Disable GraphQL introspection in the production environment by configuring your GraphQL server appropriately.

    • Implement proper access controls to ensure that only authorized users and developers can access the API schema.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    7.13 WALLET CONFIGURATION OVERWRITE VIA DIRECT ACCESS TO THE REGISTER PAGE

    //

    Low

    Description

    When a user directly accesses the registration page, he can overwrite the existing configuration, compromising the integrity of the wallet's setup and security.

    Proof of Concept

    The wallet extension allows a user to directly access the registration page. This allows users to overwrite the wallet's configuration.

    By navigating to chrome-extension://oefglhbffgfkcpboeackfgdagmlnihnh/register.html, an attacker can overwrite the wallet's settings without any authentication or authorization:

    Directly accessing the register page
    Score
    CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L(2.9)
    Recommendation

    Implement proper access control checks to prevent access to the registration page after the wallet has been configured. Ensure that only legitimate users can modify sensitive configuration settings.

    Remediation

    SOLVED: The Onbloc team solved this finding.

    Remediation Hash
    8b1e0681a44767263a7a20f1472eefa80554412a

    Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.

    © Halborn 2025. All rights reserved.