For the complete documentation index, see llms.txt. This page is also available as Markdown.

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 | Belong

  • 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

References

Contract & verifier references (expand)
  • 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?