57864 sc medium abi encodepacked hash collision vulnerability in dynamic type encoding permits malicious signature bypass enabling unauthorized and repeatable transaction execution

Submitted on Oct 29th 2025 at 09:41:02 UTC by @Saediek for Audit Comp | Belongarrow-up-right

  • Report ID: #57864

  • Report Type: Smart Contract

  • Report severity: Medium

  • Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/platform/Factory.sol

  • Impacts:

    • Unauthorized minting of NFTs

    • Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

Description

Brief/Intro

The use of abi.encodePacked with dynamic data types (strings, bytes) can result in hash collisions. This can be exploited repeatedly by a malicious actor to perform unauthorized actions (for example, creating an AccessToken collection or creating a CreditToken) bypassing signature gating enforced by the Factory signer.

Vulnerability Details

The Factory module (one of the core components) facilitates creation of AccessTokens, CreditTokens and VestingWallets. The Factory advertises "Signature Gated Deployment": deployments require approval by the configured Factory.signer. All signature verification is delegated to the SignatureVerifier Libraryarrow-up-right. The bug occurs in the implementations below:

  • checkCreditTokenInfo() https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/utils/SignatureVerifier.sol#L81

  • checkAccessTokenInfo() https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/utils/SignatureVerifier.sol#L53C14-L53C34

Both functions use abi.encodePacked on string data types (dynamic types) which can lead to collisions.

Exploit workflow (high level):

1

Step

An honest actor is approved by the Factory signer to deploy an AccessToken or CreditToken and submits a deployment transaction.

2

Step

A malicious actor crafts a different payload such that abi.encodePacked of the malicious payload produces the same packed bytes (hence same keccak256 hash) as the honest payload.

3

Step

The transaction is published. Signature check passes (same hash/signature). The Factory's token-existence check also passes (getNftInstanceInfo[hashedSalt].nftAddress == address(0)), allowing unauthorized deployment.

Root Cause

The SignatureVerifier functions checkAccessTokenInfo() and checkCreditTokenInfo() use abi.encodePacked() to compute the digest used for signature verification. abi.encodePacked concatenates encoded values without length delimiters for dynamic types, which allows different inputs to produce identical byte sequences and thus identical hashes.

Vulnerable code excerpts:

Collision Example

Because values are concatenated without boundaries, different inputs can collide:

Example shown in the report:

  • Honest payload:

    • metadata.name = "original-name"

    • metadata.symbol = "original-symbol"

    • contractURI = "https://immunefi.com/uri"

    • feeNumerator = 2000

  • Malicious payload:

    • metadata.name = "original"

    • metadata.symbol = "-nameoriginal-symbol"

    • same contractURI and feeNumerator

Then:

For a given signature, both payloads would be valid due to this hash collision, enabling unauthorized actions.

Impact Details

A malicious actor could bypass signature gating and repeatedly deploy AccessTokens and CreditTokens without authorization, breaking the access protections put in place by the Factory signer.

References

  • checkAccessTokenInfo: https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/utils/SignatureVerifier.sol#L53C14-L53C34

  • checkCreditTokenInfo: https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/utils/SignatureVerifier.sol#L81

  • Factory.produce: https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/platform/Factory.sol#L236

Proof of Concept

chevron-rightPoC: Solidity / Foundry test demonstrating collisionhashtag

(End of PoC)


Note: All original links and code references have been preserved verbatim.

Was this helpful?