Skip to content

fix(RankedBallot): Validate candidate ID bounds and uniqueness in vote()#245

Open
Muneerali199 wants to merge 1 commit intoAOSSIE-Org:mainfrom
Muneerali199:fix/ranked-ballot-duplicate-candidate-validation
Open

fix(RankedBallot): Validate candidate ID bounds and uniqueness in vote()#245
Muneerali199 wants to merge 1 commit intoAOSSIE-Org:mainfrom
Muneerali199:fix/ranked-ballot-duplicate-candidate-validation

Conversation

@Muneerali199
Copy link

Summary

Fixes two silent security vulnerabilities in RankedBallot.vote() that could corrupt election results.

Closes #244
Closes #228


Problem

Bug 1 — No bounds check on candidate IDs

If a voter submitted a voteArr containing a value >= totalCandidates, the contract would attempt to write to candidateVotes[voteArr[i]] out-of-bounds, causing an unguarded Solidity panic (array-out-of-bounds revert) with no descriptive error. Malformed input was not rejected cleanly.

Bug 2 — No uniqueness check (vote manipulation)

A voter could submit a ranking like [0, 0, 0] — the same candidate ID repeated across all positions. Since no uniqueness validation existed, the candidate at index 0 would receive points for every rank (n + (n-1) + (n-2) + ...), while all other candidates received zero. This silently corrupted results without any revert.


Fix

Added a bool[] memory seen tracking array in vote():

// Before
for (uint i = 0; i < totalCandidates; i++) {
    candidateVotes[voteArr[i]] += totalCandidates - i;
}

// After
bool[] memory seen = new bool[](totalCandidates);
for (uint i = 0; i < totalCandidates; i++) {
    uint candidateId = voteArr[i];
    if (candidateId >= totalCandidates) revert InvalidCandidateID();
    if (seen[candidateId]) revert DuplicateCandidateID();
    seen[candidateId] = true;
    candidateVotes[candidateId] += totalCandidates - i;
}

Two new typed errors added to Errors.sol:

error InvalidCandidateID();
error DuplicateCandidateID();

Both errors also registered in client/app/helpers/ErrorMessage.ts per contributing guidelines.


Files Changed

File Change
blockchain/contracts/ballots/RankedBallot.sol Added bounds check + uniqueness check in vote()
blockchain/contracts/ballots/interface/Errors.sol Added InvalidCandidateID, DuplicateCandidateID
client/app/helpers/ErrorMessage.ts Registered both new error messages

Checklist

  • Fix targets a specific, reproducible bug (not style/lint)
  • New custom errors follow existing Errors.sol interface pattern
  • ErrorMessage.ts updated per contributing guidelines
  • No unrelated changes included
  • Branch created fresh from upstream/main

RankedBallot.vote() had two security gaps:
1. No bounds check -- voteArr[i] >= totalCandidates caused an
   unguarded out-of-bounds array access (panic revert, no custom error)
2. No uniqueness check -- submitting [0,0,0] let a single candidate
   accumulate all rank-weighted points, corrupting election results

Fix: add a bool[] memory seen array to track processed IDs and revert
with new typed errors InvalidCandidateID and DuplicateCandidateID.
Also adds both new errors to Errors.sol and ErrorMessage.ts.

Closes AOSSIE-Org#244
Closes AOSSIE-Org#228
@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

Warning

Rate limit exceeded

@Muneerali199 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e411725c-6989-4a70-92c8-bfeaac2595b8

📥 Commits

Reviewing files that changed from the base of the PR and between e4df55f and 884a791.

📒 Files selected for processing (3)
  • blockchain/contracts/ballots/RankedBallot.sol
  • blockchain/contracts/ballots/interface/Errors.sol
  • client/app/helpers/ErrorMessage.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant