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

Every vulnerability and issue observed by Halborn is ranked based on two sets of Metrics and a Severity Coefficient. This system is inspired by the industry standard Common Vulnerability Scoring System.
The two Metric sets are: Exploitability and Impact. Exploitability captures the ease and technical means by which vulnerabilities can be exploited and Impact describes the consequences of a successful exploit.
The Severity Coefficients is designed to further refine the accuracy of the ranking with two factors: Reversibility and Scope. These capture the impact of the vulnerability on the environment as well as the number of users and smart contracts affected.
The final score is a value between 0-10 rounded up to 1 decimal place and 10 corresponding to the highest security risk. This provides an objective and accurate rating of the severity of security vulnerabilities in smart contracts.
The system is designed to assist in identifying and prioritizing vulnerabilities based on their level of risk to address the most critical issues in a timely manner.

4.1 EXPLOITABILITY

Attack Origin (AO):
Captures whether the attack requires compromising a specific account.
Attack Cost (AC):
Captures the cost of exploiting the vulnerability incurred by the attacker relative to sending a single transaction on the relevant blockchain. Includes but is not limited to financial and computational cost.
Attack Complexity (AX):
Describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability. Includes but is not limited to macro situation, available third-party liquidity and regulatory challenges.
Metrics:
EXPLOITABILITY METRIC (mem_e)METRIC VALUENUMERICAL VALUE
Attack Origin (AO)Arbitrary (AO:A)
Specific (AO:S)
1
0.2
Attack Cost (AC)Low (AC:L)
Medium (AC:M)
High (AC:H)
1
0.67
0.33
Attack Complexity (AX)Low (AX:L)
Medium (AX:M)
High (AX:H)
1
0.67
0.33
Exploitability EE is calculated using the following formula:

E=meE = \prod m_e

4.2 IMPACT

Confidentiality (C):
Measures the impact to the confidentiality of the information resources managed by the contract due to a successfully exploited vulnerability. Confidentiality refers to limiting access to authorized users only.
Integrity (I):
Measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of data stored and/or processed on-chain. Integrity impact directly affecting Deposit or Yield records is excluded.
Availability (A):
Measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability. This metric refers to smart contract features and functionality, not state. Availability impact directly affecting Deposit or Yield is excluded.
Deposit (D):
Measures the impact to the deposits made to the contract by either users or owners.
Yield (Y):
Measures the impact to the yield generated by the contract for either users or owners.
Metrics:
IMPACT METRIC (mIm_I)METRIC VALUENUMERICAL VALUE
Confidentiality (C)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Integrity (I)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Availability (A)None (A:N)
Low (A:L)
Medium (A:M)
High (A:H)
Critical (A:C)
0
0.25
0.5
0.75
1
Deposit (D)None (D:N)
Low (D:L)
Medium (D:M)
High (D:H)
Critical (D:C)
0
0.25
0.5
0.75
1
Yield (Y)None (Y:N)
Low (Y:L)
Medium (Y:M)
High (Y:H)
Critical (Y:C)
0
0.25
0.5
0.75
1
Impact II is calculated using the following formula:

I=max(mI)+mImax(mI)4I = max(m_I) + \frac{\sum{m_I} - max(m_I)}{4}

4.3 SEVERITY COEFFICIENT

Reversibility (R):
Describes the share of the exploited vulnerability effects that can be reversed. For upgradeable contracts, assume the contract private key is available.
Scope (S):
Captures whether a vulnerability in one vulnerable contract impacts resources in other contracts.
Metrics:
SEVERITY COEFFICIENT (CC)COEFFICIENT VALUENUMERICAL VALUE
Reversibility (rr)None (R:N)
Partial (R:P)
Full (R:F)
1
0.5
0.25
Scope (ss)Changed (S:C)
Unchanged (S:U)
1.25
1
Severity Coefficient CC is obtained by the following product:

C=rsC = rs

The Vulnerability Severity Score SS is obtained by:

S=min(10,EIC10)S = min(10, EIC * 10)

The score is rounded up to 1 decimal places.
SeverityScore Value Range
Critical9 - 10
High7 - 8.9
Medium4.5 - 6.9
Low2 - 4.4
Informational0 - 1.9

5. SCOPE

URL
(a) URL:
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

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.