DatingDapp

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

`tokenURI` builds on-chain JSON from unescaped user input (name / profileImage), allowing metadata injection

Description

Normal behavior: mintProfile stores a user-chosen name and profileImage, and tokenURI should return an ERC721 metadata JSON in which those values appear strictly as DATA — the name as the value of the "name" field, the image as the value of the "image" field — regardless of what characters the user chose.

Specific issue: tokenURI builds the metadata by directly abi.encodePacked-concatenating the raw user strings into the JSON template with no escaping and no validation at mint time. Any " (or control character) in name/profileImage therefore terminates the surrounding JSON string early, and everything after it is emitted verbatim as JSON STRUCTURE inside the Base64 payload:

abi.encodePacked('{"name":"', profileName, '", "description":"...", "attributes": [...], "image":"', imageURI, '"}')
// @> profileName / imageURI are interpolated raw — no escaping of `"` or control chars

An attacker sets a name such as pwned","image":"http://evil.example/x.png","junk":". The produced metadata then contains an attacker-controlled "image" key that PRECEDES the legitimate one, plus arbitrary injected attributes. Consequences: (1) metadata/profile spoofing — a JSON parser that takes the first duplicate key renders the attacker's image instead of the real one; (2) arbitrary injected fields (fake attributes/traits); (3) on a dating frontend that renders name as HTML, classic markup/XSS. Because the injection is baked into the on-chain, immutable token metadata, every consumer of tokenURI is exposed.

Risk

Likelihood:

  • Any user can pick a crafted name/profileImage at mint with no restriction; deterministic and self-serve.

Impact:

  • Profile/metadata spoofing (attacker-controlled image and attributes) and client-side injection/XSS on naive frontends. Bounded to metadata/UI integrity rather than on-chain fund loss, hence Low.

Proof of Concept

test/AuditSoulbound.t.sol::test_6_metadata_json_injection (PASS): name pwned","image":"http://evil.example/x.png","junk":" produces metadata whose attacker "image" key precedes the legitimate one; the contract output equals Base64.encode(craftedJson) byte-for-byte.

Recommended Mitigation

Escape "/backslash/control characters in name and profileImage (or reject them), or build the JSON with a library that escapes.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!