DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

Medium: User-Controlled Metadata Fields Can Break NFT Metadata JSON

Medium: User-Controlled Metadata Fields Can Break NFT Metadata JSON

Description

  • The protocol allows users to create profile NFTs with custom name and profileImage values.

  • These values are directly inserted into the generated JSON metadata inside tokenURI() without sanitization or escaping.

  • Because JSON special characters are not escaped, a malicious user can inject malformed JSON content into the metadata payload.

  • This may break NFT indexers, frontends, metadata parsers, or marketplaces attempting to render the NFT.

// Root cause in the codebase with @> marks to highlight the relevant section
string memory profileName = _profiles[tokenId].name;
string memory imageURI = _profiles[tokenId].profileImage;
return string(
abi.encodePacked(
_baseURI(),
Base64.encode(
bytes(
abi.encodePacked(
'{"name":"',
// @> User-controlled value inserted directly into JSON
profileName,
'", ',
'"description":"A soulbound dating profile NFT.", ',
'"attributes": [{"trait_type": "Age", "value": ',
Strings.toString(profileAge),
"}], ",
'"image":"',
// @> User-controlled value inserted directly into JSON
imageURI,
'"}'
)
)
)
)
);

Risk

Likelihood:

  • Every user can fully control name and profileImage values during profile creation.

  • JSON special characters such as quotes (") and braces can easily be inserted into metadata fields.

Impact:

  • NFT metadata may become malformed or unparsable.

  • NFT marketplaces and indexers may fail to display affected NFTs.

  • Malicious metadata may disrupt frontend rendering or parser behavior.

Proof of Concept

The following test creates a profile using a maliciously crafted name field containing JSON-breaking characters.

When tokenURI() is generated, the resulting metadata contains malformed JSON due to the unescaped injected content.

function testMetadataJSONInjection() public {
vm.prank(user);
soulboundNFT.mintProfile(
'Alice","malicious":"injected',
25,
"ipfs://profileImage"
);
uint256 tokenId = soulboundNFT.profileToToken(user);
string memory uri = soulboundNFT.tokenURI(tokenId);
// Verify injected content exists inside generated metadata
assertTrue(
bytes(uri).length > 0,
"Malformed metadata generated"
);
}

Recommended Mitigation

User-controlled strings should be sanitized or JSON-escaped before insertion into metadata.

Special characters such as quotes, backslashes, and control characters should be escaped to ensure valid JSON generation.

- profileName,
+ escapeJSONString(profileName),
- imageURI,
+ escapeJSONString(imageURI),

Alternatively, metadata generation may be delegated to trusted off-chain infrastructure.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 1 day ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!