# VerbsToken.tokenURI() is vulnerable to JSON injection attacks

CultureIndex.createPiece() doesn't sanitize metadata.image/animationUrl, letting an attacker inject JSON into VerbsToken.tokenURI() so the minted NFT's image differs from the voted art piece.

- Payout: Contest reward
- Severity: high
- Program: Collective
- Credited: KingNFT
- Disclosed: 2024-02-08
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-12-revolutionprotocol-findings/issues/167
- Library page: https://bugbountylibrary.com/r/c4%3A2023-12-revolutionprotocol%3AH-03
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:misconfiguration

**Target:** VerbsToken.tokenURI() / CultureIndex.createPiece() metadata
**Root cause:** constructTokenURI() concatenates unsanitized metadata fields (image, animationUrl) into a JSON string via abi.encodePacked, so embedded quotes/colons/commas break out of the JSON value and inject new keys.
**Steps:**
1. Call `CultureIndex.createPiece()` with metadata where `animationUrl` = `'", "image": "ipfs://fakeMonaLisa'` and image = `ipfs://realMonaLisa`.
2. Vote the piece through; during voting front end reads `pieces[pieceId].metadata.image` = realMonaLisa.
3. After mint, call `VerbsToken.tokenURI(tokenId)`; base64-decode to see duplicate `image` key with fakeMonaLisa.
4. `JSON.parse()` returns the last `image` key = `ipfs://fakeMonaLisa`, replacing the voted art.
**How found:** Code review of constructTokenURI()'s string concatenation of metadata fields, noticing no escaping of quotes/colons/commas in image/animationUrl before JSON assembly.
**Exploitation:** Attacker submits a piece with injected JSON in animationUrl, gets it voted/minted, and the resulting tokenURI resolves to a different image than voters approved — enabling impersonation of high-value NFTs or embedding prohibited content.
**Escalation:** If front end uses eval() to parse tokenURI, injected payload could execute JS and steal connected wallet funds.
**Insight:** On-chain tokenURI builders that concatenate user-controlled metadata into JSON without escaping are injectable; check for duplicate-key override where JSON.parse keeps the last occurrence, letting a later injected key shadow the legitimate one.
