Multiple votes per user possible in the forum pallet via `vote_on_poll`

Open
#10 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
rust
Domain
blockchain

Research direction

Start in runtime-modules/forum/src/lib.rs by reading vote_on_poll and ensure_vote_is_valid, then inspect how poll_alternatives and thread state are stored. Determine how prior voters, vote anonymity, and any required deposit should be represented. Done means a user cannot submit more than one vote for a poll and the behavior is covered by the forum pallet's existing validation expectations.

Written by the indexing model from the issue text.

Description

S1 - low

Summary

The vote_on_poll extrinsic in forum pallet does not check whether a user has already voted for a specific poll. This will enable a malicious forum user to submit an arbitrary number of votes and therefore manipulate the poll's result.

Issue Details

In runtime-modules/forum/src/lib.rs the vote_on_poll extrinsic can be used by forum users to vote on a specific PollAlternative by submitting it's index via this extrinsic. This extrinsic performs some validity checks via the ensure_vote_is_valid function, but this function only checks whether the poll exists and if it is not expired. Therefore a malicious forum user may submit arbitrary amount of votes and manipulate the poll's result.

    /// Check the vote is valid
    fn ensure_vote_is_valid(
        thread: Thread<ForumUserId<T>, T::CategoryId, T::Moment, T::Hash>,
        index: u32,
    ) -> Result<Poll<T::Moment, T::Hash>, Error<T>> {
        // Ensure poll exists
        let poll = thread.poll.ok_or(Error::<T>::PollNotExist)?;

        // Poll not expired
        if poll.end_time < <pallet_timestamp::Module<T>>::now() {
            Err(Error::<T>::PollCommitExpired)
        } else {
            let alternative_length = poll.poll_alternatives.len();
            // The selected alternative index is valid
            if index as usize >= alternative_length {
                Err(Error::<T>::PollData)
            } else {
                Ok(poll)
            }
        }
    }

Risk

A malicious forum user can submit an arbitrary number of votes and therefore manipulate a poll.

Mitigation

We suggest mitigating this by adding a tracking mechanism to identify which users have already voted. One possible implementation of this would be to add the voting users (forum_used_id) to the poll_alternatives field that is saved in storage. This way it can be checked whether forum_used_id already exists in any of the poll_alternatives before saving their vote. Furthermore, if the anonymity of the user's votes matter in this use case, the votes can be stored per "thread" instead of "alternatives".

Additionally, since this new implementation will store the votes on-chain, a deposit will also be required.

Dominant language
No language data
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Joystream/audits

All issues in Joystream/audits

Similar issues

More Blockchain issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.