Safeguard
Application Security•

CWE-837 Improper Enforcement of a Single, Unique Action

Votes, refunds and seat locks that should happen once can be repeated. CWE-837 is a business logic flaw. Here is how to enforce once only rules server side.

Safeguard Security Team
2 min read

CWE-837 applies when an actor should perform an action only once, or have only one unique action, but the product does not enforce it or enforces it badly. Think voting, requesting a refund, redeeming a coupon, or making a purchase. MITRE lists web based products and servers.

How it happens

The rule lives in the interface, or in a cookie, rather than in the data. A voting app that records "voted" in a cookie lets anyone vote again after clearing it. A flow that does not check existing state lets a request be replayed or sent in parallel.

MITRE's examples: a ticket booking application let a user lock a seat more than once (CVE-2008-0294); a CMS let people rate downloads by voting more than once (CVE-2005-4051); and a game registration chain let a player register multiple times and lock others out (CVE-2003-1433).

# Vulnerable: the "already voted" flag is a client cookie
if request.cookies.get("voted") != "1":
    votes[choice] += 1

What an attacker gains

MITRE says an attacker may gain an advantage over other users by repeating the action, or affect the correctness of the product, such as the result of a vote.

How to find it

The record lists no detection methods. Test it directly. List every once only action, then repeat it, replay the request, and send it in parallel. Compare the result with what the rule says.

How to fix it

The record has no formal mitigations. Practical steps:

  1. Enforce the rule on the server, keyed to an authenticated identity, not a cookie.
  2. Let the database guarantee it with a unique constraint.
  3. Make the action idempotent where possible, using request keys.
  4. Handle concurrent requests with transactions or atomic updates.
ALTER TABLE votes ADD CONSTRAINT one_vote UNIQUE (poll_id, user_id);

Click through it at your own pace, or open it full screen.

Quick check

Why is a unique database constraint better than an if statement?

Two parallel requests can both pass an if check. The constraint is enforced atomically by the database.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.