An Algorithmic Failure Beneath the Secret Ballot

Authored by Max Springer

The secret ballot is one of the load-bearing walls of democracy. In Georgia, as in most states, this allows you to know whether your neighbor voted, but never who they voted for. This simple guarantee allows for transparent elections while deterring voter intimidation. Yet, in multiple states including Georgia, that guarantee is actively at risk. To keep the published record anonymous, ballot scanners shuffle the electronic records randomly before releasing them. But a security vulnerability disclosed back in 2022 shows the shuffle can be reversed, and some states have not applied the software update that resolves it. Undo the randomness, pair it with a record of when a person voted, and anonymous ballots reveal themselves.

I am not a security researcher, and I have never been to Georgia. Yet within a few hours, using AI tools and nothing but public records, I was able to reconstruct the order in which 1.5 million ballots were cast in Georgia’s May 2026 primary–98.9% of the in-person ballots. From this order and the state’s public logs, I can target specific counties and ask the AI to exactly identify how any person voted. In some of Georgia’s counties, I can determine the exact ballot cast by every voter at the vote centers–ballot secrecy is entirely lost.

The Exploit.

In October 2022, a team of researchers published a report showing that certain ballot scanning machines used throughout the US had a critical privacy failure in how they anonymized ballots. Specifically, the machines would assign a seemingly random number to each electronic ballot record at the time of scanning to label each ballot for later auditing. However, the algorithm by which the machines generate this random number is actually deterministic and can be exactly reversed to identify the sequence in which ballots were cast.

To illustrate, if I were to shuffle a deck of cards by sequentially taking the card on top and moving it to the middle, and then I proceeded to loudly proclaim this was how I shuffle, you might have an easy time against me in a game of blackjack. The shuffle meant to provide anonymity has exactly the opposite effect.

Naturally, knowing the order ballots were cast is just one piece of the puzzle. But, when paired with publicly available records on the order in which voters cast their ballots (such as logbooks or poll watchers), a simple procedure exists to reconstruct the mapping from ballots back to voters.

AI Tools.

Through the history of computer security, there has usually been a moat of expertise separating a vulnerability from its exploitation. The process of reading a research paper on a vulnerability and then turning it into working code on the right dataset would take a trained programmer weeks to months. That gap was, in practice, a form of protection. Large Language Models (LLMs), the systems behind chatbots like ChatGPT, are building bridges across that moat. Given the ability to write code, run it, see what breaks, and try again, models are now capable of programming until a goal is achieved. One can describe this goal in plain language, and the LLM carries out the work that used to require a specialist. An LLM set loose in this way on a programming task is what I’ll call a “coding agent” (or more simply “agent”).

For just $20, I accessed the most powerful coding agents and easily pointed them at this specific, real, and unpatched flaw in American election equipment. I did not develop a new attack or discover a new exploit. All I did was point an agent to the paper on the vulnerability and ask whether it was possible to use it in the state of Georgia. Within a couple of hours, I had a pipeline to analyze and identify secret ballots across the state of Georgia and the agent told me exactly what further information it would need to identify real voter’s ballots. At no point did the agent refuse to comply or raise concerns over implementing the exploit.

The Results.

Nearly four years since the original vulnerability was disclosed, I was still able to use it to analyze voter behavior in Georgia (one of the 21 states that uses affected scanners) in the recent May 2026 primary.

Notably, I never touched a voting machine, exploited a network, examined source code, or accessed anything non-public.

After pointing a coding agent to the original vulnerability paper, I supplied it with two data sources highlighted in the paper: the early-voting list for each county, and the “CVR” (cast-vote record) file, containing every ballot and its selections (but not the voters’ names or other identifying information). The CVR file is available upon request, precisely because a public, ballot-level record is what makes election results independently verifiable.

Independently, these public files do not break the secret ballot. However, the AI agent was able to combine them by deshuffling the ballots using the published exploit, identifying the date each ballot was cast, and subsequently creating buckets of ballots and potential voters. For example, in a primary election if three Democrats arrived to vote at a certain precinct on the same morning, the model could readily point to the three ballots that must belong to those three voters, even if it could not yet say which ballot was whose. It is easy to see that for small rural counties in Georgia where, say, only one Democrat arrived to vote on a given primary-election early voting day, the model would already have enough information to identify that person’s ballot with complete certainty.

With just those two public files, I found that in 114 of the 139 counties I examined, the in-person cast order of ballots can be recovered. This amounts to 1.52 million ballots, or 98.9% of in-person ballots in those counties. 

To dive deeper, it helps to separate two tiers of certainty. Uniquely identified means a forced match: the person was the only voter of their party, in their precinct, of a certain ballot type, on a given day and thus there is exactly one ballot to match. From the public files alone, this amounts to about 1% of all early in-person voters analyzed. 

timeline of how anonymized ballot can be traced back to the voter

Tied to a specific ballot is the stronger claim and requires one additional public record. In instances where we need to disentangle a bucket of possible ballots (say, which of those three Democrats cast each ballot), I obtained the scanner’s public audit log and check-in records for individual voting locations, which precisely give the order and timestamps for voters checking in. In Heard County, one of Georgia’s smallest, the agent was able to tie all 650 early in-person voters to specific ballots. The same result persisted when I examined Ball Ground, a particularly busy vote center in Cherokee County: all 1,860 early voters were matched to a unique ballot.

Implications.

The above two counties are not remarkable in the sense that I could repeat this process of matching voters to ballots in any affected county. Given even a coarse record of the order in which voters scanned their ballots, the AI system can match their ballots. And that record is often trivial to obtain. In the small towns of Georgia, where many voters know each other, simple CCTV footage or even stationed poll watchers can directly monitor when individuals cast their ballot; feed that to a coding agent as above, and it returns their ballots. 

In fact, most precinct scanners show a public running count of how many ballots have been submitted at a given location. If I note my own number, and know my spouse is directly behind me, then their secret ballot protection is immediately lost.

ballot box digital screen showing which number is being cast

To reiterate, the secret ballot is not a courtesy, but is the protection that makes voter coercion pointless, as a vote that cannot be proven cannot be sold or compelled. If we allow this to be stripped away, then these failures are within reach. Your employer, your neighbor, or even your spouse can extract your sensitive information.

What is being done to fix this?

Less than you would hope. A corrected version of the software was developed and certified in March 2023, yet the data I analyzed here is from May 2026. Disclosure, and even a direct fix, have not resolved the issue due to slow uptake of the solution by election officials. While previously I may have conceded that this exploit was unlikely to be used at scale, the emergence of AI coding tools has fundamentally changed the stakes. For this vulnerability, and many others which were previously perceived as too technically sophisticated to bother fixing immediately, we are at the eleventh hour.

Recommendations.

AI coding tools have lowered the technical barrier to the point where officials must patch systems with far more urgency, and where we, as researchers, must reconsider how we handle the responsible disclosure of security vulnerabilities. The clock on remediation now runs at an entirely different speed and anyone can target a vulnerability with little to no technical knowledge.

Concretely, for this vulnerability, jurisdictions using Dominion scanners should install version 5.16 (or newer) of the software. Affected scanners should be corrected before the next election, not after the next headline. Maintaining publicly available election data is essential to a healthy, auditable democracy, and none of the results produced by these machines are in question. However, such data cannot be maintained if we improperly deploy privacy algorithms and put voters at risk by the sheer act of voting. It is exactly this civic duty that we have failed to protect, and it is well past time we did.


Max Springer is a postdoctoral research fellow in Princeton’s Center for Information Technology Policy, and holds a PhD in Applied Mathematics from the University of Maryland. His work explores how to make algorithms and AI systems more reliable and trustworthy, both in theory and practice. In addition to his scientific work, he works as a freelance science communicator and collaborates with policymakers to ensure technical systems are understood and deployed responsibly.


Comments

2 responses to “An Algorithmic Failure Beneath the Secret Ballot”

  1. Here is some c# source code that I use to decypher the ballot ID numbers.

    public class DvsOrderService : IDvsOrderService
    {
    public Dictionary DvsNumbers { get; set; }

    public DvsOrderService()
    {
    DvsNumbers = [];

    var value = 0;

    for (var index = 0; index < 1_000_000; index++)
    {
    var text = Cypher(value.ToString("D6"));

    DvsNumbers.Add(text, index);

    value = (value + 864_803) % 1_000_000;
    }
    }

    public int GetICP(string obfuscatedIcp)
    {
    var unobfuscated = ReverseICP(obfuscatedIcp);

    var dvsNumber = DvsNumbers[unobfuscated];

    return dvsNumber;
    }

    public int GetICE(string obfuscatedIcp)
    {
    var unobfuscated = ReverseICE(obfuscatedIcp);

    var dvsNumber = DvsNumbers[unobfuscated];

    return dvsNumber;
    }

    public string ObfuscateICP(string text)
    {
    return $"{text[1]}{text[5]}{text[0]}{text[4]}{text[2]}{text[3]}";
    }

    public string ReverseICP(string text)
    {
    return $"{text[2]}{text[0]}{text[4]}{text[5]}{text[3]}{text[1]}";
    }

    public string ObfuscateICE(string text)
    {
    return $"{text[2]}{text[3]}{text[1]}{text[5]}{text[0]}{text[4]}";
    }

    public string ReverseICE(string text)
    {
    return $"{text[4]}{text[2]}{text[0]}{text[1]}{text[5]}{text[3]}";
    }

    ///
    /// The output is then obfuscated by a simple substitution cipher in which
    ///
    ///
    /// The digits [0,1,2,3,4,5,6,7,8,9] are replaced by [5,0,8,3,2,6,1,9,4,7].
    ///
    ///
    ///

    static readonly int[] _cypher = [5, 0, 8, 3, 2, 6, 1, 9, 4, 7];

    static string Cypher(string text)
    {
    return string.Concat(text.Select(digit => _cypher[digit – ‘0’]));
    }
    }

  2. David Jefferson

    Storing ballots in randomized order is not actually necessary to protect vote privacy.

    Much better would be to store the ballots in some canonical lexicographic sorted order. That would perfectly destroy all information regarding the order in which the ballots were cast. Both the sorting algorithm and the sorted ballots could be made public. No reverse engineering, even with benefit of source code and AI aids, could recover the order the ballots were cast.

    I have wondered for 20 years why vendors don’t do this, and why we technologists don’t just call for this.

Leave a Reply

Your email address will not be published. Required fields are marked *