Platform: Code4rena
Start Date: 17/03/2023
Pot Size: $36,500 USDC
Total HM: 10
Participants: 98
Period: 3 days
Judge: leastwood
Total Solo HM: 5
Id: 223
League: ETH
Rank: 5/98
Findings: 2
Award: $1,151.77
🌟 Selected for report: 0
🚀 Solo Findings: 0
19.8705 USDC - $19.87
The user can provide one of the invalid characters for SVG/XML (eg &, <, >, etc...)
In the mint
method, there is no validation for the correctness of the biography.
Example:
Jane Doe, born in LA in 20, is an acclaimed actress & director. She starred in the hit series 'City Light' and directed the award-winning film 'Hidden Shadows'. Jane is also an animal rights activist.
tokenURI
for minted NFT and receive:{ "name": "Bio #1", "description": "Jane Doe, born in LA in 20, is an acclaimed actress & director. She starred in the hit series 'City Light' and directed the award-winning film 'Hidden Shadows'. Jane is also an animal rights activist.", "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaW5ZTWluIG1lZXQiIHZpZXdCb3g9IjAgMCA0MDAgMTAwIj48c3R5bGU+dGV4dCB7IGZvbnQtZmFtaWx5OiBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEycHg7IH08L3N0eWxlPjx0ZXh0IHg9IjUwJSIgeT0iNTAlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4geD0iNTAlIiBkeT0iMjAiPkphbmUgRG9lLCBib3JuIGluIExBIGluIDIwLCBpcyBhbiBhY2NsYWk8L3RzcGFuPjx0c3BhbiB4PSI1MCUiIGR5PSIyMCI+bWVkIGFjdHJlc3MgJiBkaXJlY3Rvci4gU2hlIHN0YXJyZWQgaW4gdDwvdHNwYW4+PHRzcGFuIHg9IjUwJSIgZHk9IjIwIj5oZSBoaXQgc2VyaWVzICdDaXR5IExpZ2h0JyBhbmQgZGlyZWN0ZWQgPC90c3Bhbj48dHNwYW4geD0iNTAlIiBkeT0iMjAiPnRoZSBhd2FyZC13aW5uaW5nIGZpbG0gJ0hpZGRlbiBTaGFkb3dzJy48L3RzcGFuPjx0c3BhbiB4PSI1MCUiIGR5PSIyMCI+IEphbmUgaXMgYWxzbyBhbiBhbmltYWwgcmlnaHRzIGFjdGl2aXN0LjwvdHNwYW4+PC90ZXh0Pjwvc3ZnPg==" }
image
field from the result and sets src
attribute of img
to display bio#0 - c4-judge
2023-03-28T03:58:00Z
0xleastwood marked the issue as duplicate of #212
#1 - c4-judge
2023-04-11T19:36:17Z
0xleastwood marked the issue as satisfactory
19.8705 USDC - $19.87
https://github.com/code-423n4/2023-03-canto-identity/blob/077372297fc419ea7688ab62cc3fd4e8f4e24e66/canto-bio-protocol/src/Bio.sol#L121 https://github.com/code-423n4/2023-03-canto-identity/blob/077372297fc419ea7688ab62cc3fd4e8f4e24e66/canto-bio-protocol/src/Bio.sol#L43
I don't know if this is in the scope, but it will be useful
Examples of bad biographies
Load an invalid photo
"<image href='http://surl.li/fphve'/>"
Execute JS
"<script>console.log('WOW')</script>"
But actually, it's not so bad because there are 2 things that make it difficult to use:
data:image/svg+xml;base64
typeThe first makes it difficult to work with long links. If data is used and it is not decoded, then the code will not be executed, but only until the user clicks on the photo link...
Everything changes if the data is decoded and inserted as svg... Then the code will be executed and injected
example decode svg from tokenURI
for test:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 100"> <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle"><tspan x="50%" dy="20"><script>console.log('WOW')</script></tspan></text> </svg>
#0 - c4-judge
2023-03-28T03:57:50Z
0xleastwood marked the issue as duplicate of #212
#1 - c4-judge
2023-04-11T19:36:12Z
0xleastwood marked the issue as satisfactory
1131.9044 USDC - $1,131.90
The task of the tokenURI
method is to return a json
object with a generated svg where the biography up to 200 bytes long is divided by 40 per line. This was implemented by iterating through each character of the bio
, with a large number of operations. Which makes it difficult to understand, increases the possibility of making mistakes, the cost of a method call, etc.
I recommend transferring the line break to the shoulders of SVG tags and styles, which will simplify and make the code many times cheaper, and get rid of potential errors.
An example is given below:
Actual code code +-43 lines, 14 variables, a lot differens operations
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 100"> <style> text { font-family: sans-serif; font-size: 12px; } </style> <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle"> <tspan x="50%" dy="20">Jane Doe, born in LA in 20, is an acclai</tspan> <tspan x="50%" dy="20">med actress director. She starred in t</tspan> <tspan x="50%" dy="20">he hit series 'City Light' and directed </tspan> <tspan x="50%" dy="20">the award-winning film 'Hidden Shadows'.</tspan> <tspan x="50%" dy="20"> Jane is also an animal rights activist.</tspan> </text> </svg>
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 200"> <style> .c { display: flex; align-items: center; justify-content: center; height: 100%; } .bio { font-family: sans-serif; font-size: 12px; max-width: 34ch; line-height: 20px; hyphens: auto; } </style> <foreignObject width="100%" height="100%"> <div class="c" xmlns="http://www.w3.org/1999/xhtml"> <div class="bio">Jane Doe, born in LA in 20, is an acclaimed actress director. She starred in the hit series 'City Light' and directed the award-winning film 'Hidden Shadows'. Jane is also an animal rights activist.</div> </div> </foreignObject> </svg>
This is just an example. The point is to use svg, css tags in order to reduce the complexity of the code many times
We can see that there is more plain text.
But now we don't have to worry about the following things:
Now we need to return only the template and insert the bio in the center of the template Code will look like:
function tokenURI(uint256 _id) public view override returns (string memory) { if (_ownerOf[_id] == address(0)) revert TokenNotMinted(_id); string memory bioText = bio[_id]; bytes memory imageBytes = bytes( string.concat( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 200"><style>.c{display:flex;align-items:center;justify-content:center;height:100%;}.bio{font-family:sans-serif;font-size:12px;max-width:34ch;line-height:20px;hyphens:auto;}</style><foreignObject width="100%" height="100%"><div class="c" xmlns="http://www.w3.org/1999/xhtml"><div class="bio">', bioText, "</div></div></foreignObject></svg>" ) ); string memory json = Base64.encode( bytes( string.concat( '{"name": "Bio #', LibString.toString(_id), '", "description": "', bioText, '", "image": "data:image/svg+xml;base64,', Base64.encode(imageBytes), '"}' ) ) ); return string.concat("data:application/json;base64,", json); }
We see a colossal simplification, With the avoidance of many moments
Compare this with actual code code the method became cheaper by an order of magnitude, the complexity was reduced to a minimum. Now there are only 2 limitations for the biography, these are: length, and limitations to the XML
text
#0 - c4-sponsor
2023-03-29T20:50:02Z
OpenCoreCH marked the issue as sponsor confirmed
#1 - OpenCoreCH
2023-03-29T20:51:05Z
Very good PoC, thanks for that! I think I'll ultimately go with the approach the warden suggested, as handling all edge cases properly on-chain is quite complex and error-prone.
#2 - 0xleastwood
2023-04-10T20:08:27Z
Very good PoC, thanks for that! I think I'll ultimately go with the approach the warden suggested, as handling all edge cases properly on-chain is quite complex and error-prone.
While I'd say this issue is extremely comprehensive, I don't really see any security vulnerability. These improvements are mostly cosmetic in nature so I think it makes sense to downgrade to QA.
#3 - c4-judge
2023-04-10T20:08:37Z
0xleastwood changed the severity to QA (Quality Assurance)
#4 - c4-judge
2023-04-10T20:21:44Z
This previously downgraded issue has been upgraded by 0xleastwood
#5 - c4-judge
2023-04-10T20:21:45Z
This previously downgraded issue has been upgraded by 0xleastwood
#6 - c4-judge
2023-04-10T20:22:03Z
0xleastwood marked the issue as duplicate of #59
#7 - 0xleastwood
2023-04-10T20:22:43Z
After further consideration, this seems to be a pretty important aspect of the protocol that should be addressed.
#8 - c4-judge
2023-04-11T19:55:54Z
0xleastwood marked the issue as satisfactory