Skip to main content
Sigvex

ERC-165 Interface Spoofing Remediation

How to avoid trusting a forged supportsInterface response by verifying behaviour, not just the interface flag.

ERC-165 Interface Spoofing Remediation

Overview

Related Detector: ERC-165 Interface Spoofing

supportsInterface(bytes4) is a self-report: a contract can return true for any interface id, whether or not it implements the behaviour. Routers, marketplaces, and bridges that branch on the result can be tricked into treating a hostile contract as a standard token. The remediation is to treat ERC-165 as a hint, not proof — verify the behaviour you depend on, and never grant trust on the flag alone.

Before (Vulnerable)

function list(address nft, uint256 id) external {
    // A malicious contract can return true here without behaving like an ERC-721.
    require(IERC165(nft).supportsInterface(type(IERC721).interfaceId), "Not ERC721");
    _escrow(nft, id);
}

After (Fixed — verify behaviour and outcomes)

function list(address nft, uint256 id) external {
    require(nft.code.length > 0, "Not a contract");
    // Confirm the interface claim, then rely on the actual transfer succeeding and
    // the post-conditions holding, not on the self-reported flag.
    try IERC721(nft).ownerOf(id) returns (address owner) {
        require(owner == msg.sender, "Not owner");
    } catch {
        revert("Not ERC721");
    }
    IERC721(nft).transferFrom(msg.sender, address(this), id);
    require(IERC721(nft).ownerOf(id) == address(this), "Escrow failed");
}

Base authorization and accounting on verified outcomes (ownership before and after a transfer), so a spoofed supportsInterface cannot buy the attacker anything.

Common Mistakes

  • Using supportsInterface as an access-control gate rather than a capability hint.
  • Checking the interface id but skipping the post-condition check that the operation actually did what a real token would do.
  • Assuming an ERC-165 true implies a specific fee or royalty behaviour (e.g. ERC-2981) without validating the returned values.

References