Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Unrestricted burn() Lacks Ownership Check, Allowing Malicious Users to Destroy Any NFT

[H-3] Unrestricted burn() Lacks Ownership Check, Allowing Malicious Users to Destroy Any NFT

Description

The burn() function in BidBeasts_NFT_ERC721.sol lacks ownership or approval checks. Unlike standard ERC721 implementations such as OpenZeppelin’s ERC721Burnable, which enforce _isApprovedOrOwner(msg.sender, tokenId), this implementation allows any external account to destroy NFTs without restrictions.

// @audit No ownership check (anyone can burn NFTs).
function burn(uint256 _tokenId) public {
_burn(_tokenId);
emit BidBeastsBurn(msg.sender, _tokenId);
}

Risk

Likelihood:

Very High – requires no special privileges, cost, or complex conditions. Any external address can call burn(tokenId) directly.

Impact:

Critical – Permanent and irreversible destruction of NFTs, including those owned by other users. This can cause:

  • Breaking ERC721 invariants (ownership and approval rules).

  • Potential Denial of Service (DoS): listed NFTs could be destroyed during auctions or trades.

  • Loss of user funds if NFTs are destroyed mid-sale.

  • Damage to marketplace reputation and trust.

Proof of Concept

function test_exploit_unauthorizedBurn() public {
// 1) Owner mints NFT to SELLER
vm.prank(OWNER);
uint256 tokenId = nft.mint(SELLER);
// Sanity check: SELLER owns the NFT
assertEq(nft.ownerOf(tokenId), SELLER, "SELLER should own the NFT");
// 2) Random attacker (not owner, not approved) calls burn()
address attacker = address(0xBEEF);
vm.prank(attacker);
nft.burn(tokenId); // no ownership check inside burn()
// 3) Assert that NFT is permanently destroyed
vm.expectRevert(); // should revert because tokenId no longer exists
nft.ownerOf(tokenId);
// Impact: attacker destroyed SELLER’s NFT
}
forge test --match-test test_exploit_unauthorizedBurn -vvv

Recommended Mitigation

  • Restrict burn() to the token owner or an approved operator by using the internal _isApprovedOrOwner() check.

  • Use OpenZeppelin’s ERC721Burnable as a reference.

- function burn(uint256 _tokenId) public {
- _burn(_tokenId);
- emit BidBeastsBurn(msg.sender, _tokenId);
- }
+ function burn(uint256 _tokenId) public {
+ require(
+ _isApprovedOrOwner(msg.sender, _tokenId),
+ "Caller is not owner nor approved"
+ );
+ _burn(_tokenId);
+ emit BidBeastsBurn(msg.sender, _tokenId);
+ }

Benefits:

  • Prevents unauthorized destruction of NFTs.

  • Preserves ERC721 ownership invariants.

  • Protects marketplace trust and user assets.

Updates

Lead Judging Commences

cryptoghost Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts ERC721: Anyone Can Burn

In the BidBeasts ERC721 implementation, the burn function is publicly accessible, allowing any external user to burn NFTs they do not own. This exposes all tokens to unauthorized destruction and results in permanent asset loss.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!