57634 sc medium unauthorized minting of nfts due to signature replay

Submitted on Oct 27th 2025 at 19:25:33 UTC by @Oxv1bh4 for Audit Comp | Belongarrow-up-right

  • Report ID: #57634

  • Report Type: Smart Contract

  • Report severity: Medium

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

  • Impacts:

    • Unauthorized minting of NFTs

Description

Brief/Intro

A valid minting signature can be replayed across different NFT collections deployed on the platform. This allows unauthorized minting of NFTs in other collections using a signature originally issued for a different one.

Vulnerability Details

In the AccessToken contract, the functions mintStaticPrice and mintDynamicPrice handle the minting of new NFTs within a collection. Each minting action is authorized using a backend-generated EIP-712 signature that includes the fields: receiver, tokenId, tokenUri, whitelisted, and block.chainid.

Because the signature does not include any unique identifier that ties it to a specific NFT collection, the same signature can be reused to mint an NFT with the same tokenId and tokenUri in another collection. This leads to a replay scenario where a signature approved for one collection can be replayed across different collections.

The following SignatureVerifier library functions used to verify static and dynamic price minting signatures lack a unique collection-level identifier in the signed payload. As a result, a valid signature can be replayed across multiple NFT collections, enabling unauthorized minting without additional approval.

function checkStaticPriceParameters(address signer, address receiver, StaticPriceParameters calldata params)
        external
        view
    {
        require(
            signer.isValidSignatureNow(
                keccak256(
                    abi.encodePacked(receiver, params.tokenId, params.tokenUri, params.whitelisted, block.chainid)
                ),
                params.signature
            ),
            InvalidSignature()
        );
    }
function checkDynamicPriceParameters(address signer, address receiver, DynamicPriceParameters calldata params)
        external
        view
    {
        require(
            signer.isValidSignatureNow(
                keccak256(abi.encodePacked(receiver, params.tokenId, params.tokenUri, params.price, block.chainid)),
                params.signature
            ),
            InvalidSignature()
        );
    }

Impact Details

A valid signature can be replayed across collections, allowing unauthorized NFT mints - CRITICAL

circle-exclamation

References

chevron-rightContract & verifier references (expand)hashtag
  • AccessToken.sol::mintStaticPrice : https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/tokens/AccessToken.sol?utm_source=immunefi#L173-L199

  • AccessToken.sol::mintDynamicPrice : https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/tokens/AccessToken.sol?utm_source=immunefi#L209-L230

  • SignatureVerifier.sol::checkStaticPriceParameters : https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/utils/SignatureVerifier.sol#L239-L252

  • SignatureVerifier.sol::checkDynamicPriceParameters : https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/utils/SignatureVerifier.sol#L221-L232

Proof of Concept

Include the following test case within the Mint describe block in test/v2/tokens/accessToken.test.sol.

Run the command npm run test

Was this helpful?