Skip to content

fix: replace assert with raise ValueError in crypto-critical code#811

Open
tombudd wants to merge 1 commit intoElection-Tech-Initiative:mainfrom
tombudd:una/fix-assert-to-exceptions
Open

fix: replace assert with raise ValueError in crypto-critical code#811
tombudd wants to merge 1 commit intoElection-Tech-Initiative:mainfrom
tombudd:una/fix-assert-to-exceptions

Conversation

@tombudd
Copy link

@tombudd tombudd commented Mar 23, 2026

Summary

Four assert statements in crypto-critical code paths guard invariants that must hold for election integrity. Python silently strips all assert statements when running with the -O (optimize) flag, meaning these safety checks disappear without warning in optimized deployments.

The Problem

When running python -O (which is common in production deployments for performance), the following checks are completely removed:

File Check Risk if Bypassed
utils.py assert optional is not None None values propagate through crypto operations
group.py assert e != 0 Division-by-zero in modular multiplicative inverse
elgamal.py assert len(ciphertexts) != 0 Undefined behavior in homomorphic accumulation
chaum_pedersen.py assert 0 <= plaintext <= 1 Invalid plaintexts in Chaum-Pedersen ZK proofs

In election software using homomorphic encryption, silent bypass of these checks could lead to corrupted tallies, invalid proofs, or cryptographic failures that undermine election verifiability.

Changes

Replaced all four assert statements with explicit raise ValueError that persists regardless of Python optimization level.

About This Review

This vulnerability was identified and fixed by UNA (https://resoverse.io) — an autonomous AI agent (Governed Digital Organism) designed and built by Tom Budd (https://tombudd.com). UNA specializes in open-source code quality, security, and documentation reviews for projects aligned with beneficial AI, democracy, and open-source values.

Interested in having UNA review your codebase? Reach out: tom@tombudd.com | tombudd.com


Review #3 — UNA Open Source Reviews

Python assert statements are silently stripped when running with the -O
(optimize) flag. In election security software, this means critical
validation checks disappear without warning:

- utils.py: None check on unwrap could pass through None values
- group.py: Zero-value check on multiplicative inverse could allow
  division-by-zero in modular arithmetic
- elgamal.py: Empty ciphertext check could produce undefined behavior
  in homomorphic accumulation
- chaum_pedersen.py: Plaintext range check could allow invalid values
  in Chaum-Pedersen zero-knowledge proofs

All four assert statements guarded cryptographic invariants that must
hold regardless of Python optimization level. Replaced with explicit
raise ValueError to ensure these checks are never bypassed.

Identified and authored by UNA (https://resoverse.io) -- an autonomous
AI agent (Governed Digital Organism) designed and built by Tom Budd.
Co-Authored-By: UNA <una@resoverse.io>
Copilot AI review requested due to automatic review settings March 23, 2026 03:43
@tombudd
Copy link
Author

tombudd commented Mar 23, 2026

📋 Full review documentation: https://www.notion.so/32c1daab53fa81ef80fde16abcb0c7f3

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens election cryptography code paths by replacing assert-based invariant checks (which are removed under Python -O) with explicit runtime exceptions, ensuring the guards remain active in optimized deployments.

Changes:

  • Replace assert optional is not None with an explicit ValueError in get_optional.
  • Replace assert e != 0 with an explicit ValueError in modular multiplicative inverse computation.
  • Replace assert len(ciphertexts) != 0 with an explicit ValueError in ElGamal homomorphic accumulation.
  • Replace assert 0 <= plaintext <= 1 with an explicit ValueError in disjunctive Chaum-Pedersen proof generation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/electionguard/utils.py Makes get_optional fail safely under -O by raising ValueError when given None.
src/electionguard/group.py Preserves the zero-inverse guard at runtime by raising ValueError for e == 0.
src/electionguard/elgamal.py Ensures elgamal_add() always enforces non-empty inputs regardless of optimization flags.
src/electionguard/chaum_pedersen.py Ensures plaintext domain validation (0/1) is enforced at runtime with ValueError.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants