@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Prevent users from voting for invalid Slowvote options

Summary:
Depends on D19773. See <https://hackerone.com/reports/434116>. You can currently vote for invalid options by submitting, e.g., `vote[]=12345`.

By doing this, you can see the responses, which is sort of theoretically a security problem? This is definitely a bug, regardless.

Instead, only allow users to vote for options which are actually part of the poll.

Test Plan:
- Tried to vote for invalid options by editing the form to `vote[]=12345` (got error).
- Tried to vote for invalid options by editing the radio buttons on a plurality poll into checkboxes, checking multiple boxes, and submitting (got error).
- Voted in approval and plurality polls the right way, from the main web UI and from the embed (`{V...}`) UI.

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D19774

+25 -13
+25 -13
src/applications/slowvote/controller/PhabricatorSlowvoteVoteController.php
··· 7 7 $viewer = $request->getViewer(); 8 8 $id = $request->getURIData('id'); 9 9 10 + if (!$request->isFormPost()) { 11 + return id(new Aphront404Response()); 12 + } 13 + 10 14 $poll = id(new PhabricatorSlowvoteQuery()) 11 15 ->setViewer($viewer) 12 16 ->withIDs(array($id)) ··· 16 20 if (!$poll) { 17 21 return new Aphront404Response(); 18 22 } 23 + 19 24 if ($poll->getIsClosed()) { 20 25 return new Aphront400Response(); 21 26 } 22 27 23 28 $options = $poll->getOptions(); 24 - $viewer_choices = $poll->getViewerChoices($viewer); 29 + $options = mpull($options, null, 'getID'); 25 30 26 - $old_votes = mpull($viewer_choices, null, 'getOptionID'); 27 - 28 - if (!$request->isFormPost()) { 29 - return id(new Aphront404Response()); 30 - } 31 + $old_votes = $poll->getViewerChoices($viewer); 32 + $old_votes = mpull($old_votes, null, 'getOptionID'); 31 33 32 34 $votes = $request->getArr('vote'); 33 35 $votes = array_fuse($votes); 34 36 35 - $this->updateVotes($viewer, $poll, $old_votes, $votes); 37 + $method = $poll->getMethod(); 38 + $is_plurality = ($method == PhabricatorSlowvotePoll::METHOD_PLURALITY); 36 39 37 - return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID()); 38 - } 40 + if ($is_plurality && count($votes) > 1) { 41 + throw new Exception( 42 + pht('In this poll, you may only vote for one option.')); 43 + } 39 44 40 - private function updateVotes($viewer, $poll, $old_votes, $votes) { 41 - if (!empty($votes) && count($votes) > 1 && 42 - $poll->getMethod() == PhabricatorSlowvotePoll::METHOD_PLURALITY) { 43 - return id(new Aphront400Response()); 45 + foreach ($votes as $vote) { 46 + if (!isset($options[$vote])) { 47 + throw new Exception( 48 + pht( 49 + 'Option ("%s") is not a valid poll option. You may only '. 50 + 'vote for valid options.', 51 + $vote)); 52 + } 44 53 } 45 54 46 55 foreach ($old_votes as $old_vote) { ··· 60 69 ->setOptionID($vote) 61 70 ->save(); 62 71 } 72 + 73 + return id(new AphrontRedirectResponse()) 74 + ->setURI($poll->getURI()); 63 75 } 64 76 65 77 }