You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a mock address is registered to another user, it loses its reviews, votes, and comments
Summary
In Ethos, each user has a profile identified by a unique id, that can have multiple addresses. Profiles can receive reviews, votes, attestations, and comments.
If an address doesn't belong to a profile, a new MOCK profile is created. Mock profiles track reviews, votes and comments made without an associated subject profileId. Each address is mapped to a profileId in the profileIdByAddress mapping, including mock profiles. When someone leaves a review for a mock profile, the review is mapped to the mock's profileId in the reviewIdsBySubjectProfileId mapping.
Eventually, if the the owner of the address attached to the mock profile has a actual actual profile, they can register the address (attached to the mock profile) to their actual profile by calling the registerAddress() function in EthosProfile.sol. The function updates the profileIdByAddress mapping to point to the actual profileId and remove the address from the mock profile.
Afterward, when we check the profileId for the address, it will return a profileId different from the mock profile's. This is the intended behavior, as the address is now part of the actual profile.
The problem arises in the EthosReview.sol contract, where reviewIdsBySubjectProfileId is not updated when the address is registered to the actual profile. This means that the review remains associated with the mock profile but not with the address, causing reviewIdsBySubjectAddress() to not functio as expected, leading to lost reviews.
Same vulnerability also exists in the EthosDiscussion.sol and EthosVotes contracts, where replies[ethosProfile][targetId] and votesGeneralByContractByTargetId[ethosProfile][targetId] are also not updated when the address is registered to an actual profile.
This is important, beacuse reviews, discussions and votes are used for off-chain reputation score calculation. Losing them can lead to a loss of reputation.
The Credibility Score algorithm will factor in a variety of weighted indicators. Indicators include relevant on chain actions, such as:
average review rating and volume of reviews
Under the hood
The credibility score will be calculated using on chain Ethos protocol data only. The algorithm will be committed to the Ethos Smart Contract, with all details publicly verifiable.
Address is registered as a secondary address to an actual profile.
External pre-conditions
None
Attack Path
Scenario:
0x123 is an address with a mock profile.
0x456 is an address with an actual profile.
Alice owns both addresses
Bob leaves a review for 0x123.
Bob also votes for 0x123.
Alice registers 0x123 to her actual profile.
Bob checks his reviews and votes for 0x123 and gets 0 results.
Impact
reviewIdsBySubjectAddress() in EthosReview.sol
hasVotedFor() and votesInRangeFor() in EthosVote.sol
directRepliesInRange() and addReply() in EthosDiscussion.sol
will not return all reviews, votes, and comments associated with the address (only those specifically written for the verified profile before the registration).
Users will lose reviews and discussions associated with their mock profile upon registering the address to an actual profile, which will lead to incorrect off-chain reputation score calculations.
PoC
Place the following code in address.register.test.ts:
Click to see the code
// eslint-disable-next-line jest/no-focused-testsit.only('should lose reviews when a mock profile’s address is registered to another user',async()=>{constethosReview: EthosReview=deployer.ethosReview.contract;constuserAAddress2=awaitdeployer.newWallet();awaituserB.review({address: userAAddress2.address});// Verify the review was createdconstuserAAddress2ProfileId=awaitethosProfile.profileIdByAddress(userAAddress2.address);constreviews=awaitethosReview.reviewsBySubjectInRange(userAAddress2ProfileId,0,10);// userAAddress2 should own 1 reviewexpect(reviews.length).to.equal(1);expect(reviews[0][3]).to.equal(userAAddress2.address);// Review.subject// at this point userAAddress2 should be mapped to a mock profileconstuserAAddress2Status=awaitethosProfile.profileStatusById(userAAddress2ProfileId);expect(userAAddress2Status[2]).to.equal(true);// Mock == trueexpect(userAAddress2Status[0]).to.equal(false);// Verified == false// Register userAAddress2 to userAawaitregisterAddress(userA,userAAddress2.address);// verify userAAddress2 is now part of userA's profileconstuserAAddresses=awaitethosProfile.addressesForProfile(userA.profileId);expect(userAAddresses.length).to.equal(2);expect(userAAddresses[0]).to.equal(userA.signer.address);expect(userAAddresses[1]).to.equal(userAAddress2.address);constuserAAddress2ProfileIdNEW=awaitethosProfile.profileIdByAddress(userAAddress2.address);// verify the review is no longer associated with userAAddress2constreviewsAfterRegistration=awaitethosReview.reviewsBySubjectInRange(userAAddress2ProfileIdNEW,0,10,);// review still exists but is no longer associated with userAAddress2 as// it is mapped to the old profileId of userAAddress2 and doesn't get updatedexpect(reviewsAfterRegistration.length).to.equal(0);});
Mitigation
Update the profileId in the reviewIdsBySubjectProfileId, votesGeneralByContractByTargetId and replies mappings when the address is registered to an actual profile using registerAddress().
⚠ Be cautious when updating these mappings, as a user may write a review for a mock profile before registering the address to their actual profile, which would cause the user to review themselves.
The text was updated successfully, but these errors were encountered:
sherlock-admin4
changed the title
Quaint Nylon Caterpillar - When a mock address is registered to another user, it loses its reviews, votes, and comments
Bozho - When a mock address is registered to another user, it loses its reviews, votes, and comments
Nov 20, 2024
Bozho
High
When a mock address is registered to another user, it loses its reviews, votes, and comments
Summary
In Ethos, each user has a profile identified by a unique id, that can have multiple addresses. Profiles can receive reviews, votes, attestations, and comments.
If an address doesn't belong to a profile, a new MOCK profile is created. Mock profiles track reviews, votes and comments made without an associated subject
profileId
. Each address is mapped to aprofileId
in theprofileIdByAddress
mapping, including mock profiles. When someone leaves a review for a mock profile, the review is mapped to the mock'sprofileId
in thereviewIdsBySubjectProfileId
mapping.Eventually, if the the owner of the address attached to the mock profile has a actual actual profile, they can register the address (attached to the mock profile) to their actual profile by calling the
registerAddress()
function inEthosProfile.sol
. The function updates theprofileIdByAddress
mapping to point to the actual profileId and remove the address from the mock profile.EthosProfile.sol#404
Afterward, when we check the
profileId
for the address, it will return aprofileId
different from the mock profile's. This is the intended behavior, as the address is now part of the actual profile.The problem arises in the
EthosReview.sol
contract, wherereviewIdsBySubjectProfileId
is not updated when the address is registered to the actual profile. This means that the review remains associated with the mock profile but not with the address, causingreviewIdsBySubjectAddress()
to not functio as expected, leading to lost reviews.Same vulnerability also exists in the
EthosDiscussion.sol
andEthosVotes
contracts, wherereplies[ethosProfile][targetId]
andvotesGeneralByContractByTargetId[ethosProfile][targetId]
are also not updated when the address is registered to an actual profile.This is important, beacuse reviews, discussions and votes are used for off-chain reputation score calculation. Losing them can lead to a loss of reputation.
Sources:
Whitepaper
Another page of whitepaper
Sponsor in the public channel
Sponsor confirming the issue in the private thread:
Root Cause
The following mappings are not updated when an address of a mock profile is registered to an actual profile:
reviewIdsBySubjectProfileId[subjectProfileId]
@EthosReview.sol
replies[ethosProfile][targetId]
@EthosDiscussion.sol
votesGeneralByContractByTargetId[targetContract][targetId]
@EthosVote.sol
Internal pre-conditions
External pre-conditions
None
Attack Path
Scenario:
Impact
reviewIdsBySubjectAddress()
inEthosReview.sol
hasVotedFor()
andvotesInRangeFor()
inEthosVote.sol
directRepliesInRange()
andaddReply()
inEthosDiscussion.sol
will not return all reviews, votes, and comments associated with the address (only those specifically written for the verified profile before the registration).
Users will lose reviews and discussions associated with their mock profile upon registering the address to an actual profile, which will lead to incorrect off-chain reputation score calculations.
PoC
Place the following code in
address.register.test.ts
:Click to see the code
Mitigation
Update the
profileId
in thereviewIdsBySubjectProfileId
,votesGeneralByContractByTargetId
andreplies
mappings when the address is registered to an actual profile usingregisterAddress()
.⚠ Be cautious when updating these mappings, as a user may write a review for a mock profile before registering the address to their actual profile, which would cause the user to review themselves.
The text was updated successfully, but these errors were encountered: