Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

```Soulmate::writeMessageInSharedSpace``` unauthorized access to shared space by initial user without soulmate

Summary

The Soulmate::writeMessageInSharedSpace function allows any user with a valid ID to write a message in the shared space. However, a user who hasn't called mintSoulmateToken has an ID of 0 . In this way, he/she can write a message in the shared space of the soulmate pair that have the id = 0 and overwrite their messages.

Vulnerability Details

The function does not validate that the caller is a legitimate soulmate before updating the shared space. This means that the initial user without a soulmate can overwrite messages intended for the soulmates who are assigned the ID of 0.

function writeMessageInSharedSpace(string calldata message) external {
@> uint256 id = ownerToId[msg.sender];
sharedSpace[id] = message;
emit MessageWrittenInSharedSpace(id, message);
}

Impact

function testUserIdZeroCanOverwriteMessage() public {
//Soulmate1 is united with soulmate2
vm.prank(soulmate1);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate2);
soulmateContract.mintSoulmateToken();
assertEq(soulmateContract.soulmateOf(soulmate1), soulmate2);
assertEq(soulmateContract.soulmateOf(soulmate2), soulmate1);
//Solmate1 write a message in the shared space to soulmate2
vm.startPrank(soulmate1);
console2.log("The soulmate1 id:", soulmateContract.ownerToId(soulmate1));
soulmateContract.writeMessageInSharedSpace("Buy some eggs");
vm.stopPrank();
//Read the message in the shared space
string memory messageSoulmate1Before = soulmateContract.readMessageInSharedSpace();
console2.log("The soulmate1 message is:", messageSoulmate1Before);
vm.startPrank(user);
console2.log("The user id:", soulmateContract.ownerToId(user));
//A user writes a message in the same shared space
soulmateContract.writeMessageInSharedSpace("Buy milk, please");
vm.stopPrank();
string memory messageUser = soulmateContract.readMessageInSharedSpace();
console2.log("The user message is:", messageUser);
//The soulmate1 message is overwritten by the user message
string memory messageSoulmate1After = soulmateContract.readMessageInSharedSpace();
console2.log("The final message in the shared space is:", messageSoulmate1After);
assert(
keccak256(abi.encodePacked(messageSoulmate1Before)) != keccak256(abi.encodePacked(messageSoulmate1After))
);
}
[PASS] testUserIdZeroCanOverwriteMessage() (gas: 264553)
Logs:
The soulmate1 id: 0
The soulmate1 message is: Buy some eggs, darling
The user id: 0
The user message is: Buy milk, please, darling
The final message in the shared space is: Buy milk, please, darling
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.17ms

Tools Used

Manual review

Recommendations

Modify the writeMessageInSharedSpace function to include a check that ensures the caller is a soulmate before allowing them to update the shared space.

function writeMessageInSharedSpace(string calldata message) external {
uint256 id = ownerToId[msg.sender];
+. require(soulmateOf[msg.sender] != address(0), "Not a soulmate");
sharedSpace[id] = message;
emit MessageWrittenInSharedSpace(id, message);
}
Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-write-message-nft-0-id

Medium Severity, This has an indirect impact and influence on the possibility of divorce between soulmates owning the first soulmate NFT id0, leading to permanent loss of ability to earn airdrops/staking rewards.

Support

FAQs

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