12 min read

Roll Until You Pass: The Retry Loophole That Quietly Defeats Age Estimation

Australia's eSafety flagged platforms for letting under-16s retry age checks until they pass. Here's the statistics of retry abuse — and the attempt-budget architecture that closes it.

A facial age estimation check rendered as a slot machine: an under-threshold face feeding repeated attempts into a probabilistic gate until a '16+' result lands, with an attempt-budget counter blocking the retry loop

In its first compliance update since Australia’s Social Media Minimum Age law took effect, the eSafety Commissioner listed the ways the largest platforms were still letting under-16s through. One line should stop any engineer who has ever shipped an age check: platforms were “enabling children aged under 16 to repeatedly attempt the same age assurance method to ultimately obtain a 16+ outcome.”

That is not a description of a clever exploit. It is a description of a default. Any age check that returns a probabilistic verdict and lets the same user try again has built a slot machine, and the house does not win. Dr. Rob Nicholls of the University of Sydney put it bluntly: “The platforms engineered workarounds into their own age assurance systems… and allowed repeated attempts to game facial recognition.” The word that matters there is engineered. The regulator is no longer treating the retry loophole as a bug someone forgot to fix. It is treating it as a design decision — and it has narrowed its enforcement focus to five platforms (Facebook, Instagram, Snapchat, TikTok, YouTube) with a decision on action expected by the middle of 2026, and penalties up to AUD 49.5 million per systemic failure.

This post is about the part of that finding that generalizes beyond Australia: the math of retry abuse, why it is worse than it looks, and the attempt-budget architecture that actually closes it.

A check with a retry button is a slot machine

Start from what facial age estimation (FAE) actually is. It is not a measurement of age; it is a probabilistic classification with a known, documented error band that gets wider near any threshold you care about. eSafety’s own report concedes this: FAE is “an effective form of age assurance” — “in particular, for confirming that a person is considerably younger or older than a given age threshold” — but it is “known to have higher error rates for children near the age threshold of 16 years.” We have walked through the NIST FATE benchmark numbers before: a 14- or 15-year-old sitting right under the line is exactly the case where the model is least certain and the false-positive rate is highest.

Call that per-attempt false-acceptance probability p — the chance that a given near-threshold minor gets a wrong “16+” verdict on a single try. For a 14-year-old near the line, p is not small. Now let them try again. And again. If attempts were independent, the probability that a minor eventually clears the gate after N tries is 1 − (1 − p)^N, which climbs toward certainty fast:

Attempts (N) Pass probability at p = 5% Pass probability at p = 10%
1 5% 10%
5 23% 41%
10 40% 65%
25 72% 93%
50 92% 99%
100 99% ~100%

A model with a respectable 5% near-threshold false-acceptance rate — which would look fine in a vendor datasheet — hands a determined 14-year-old a coin-flip chance by attempt ten and a near-guarantee by attempt fifty. The single-shot accuracy you bought is not the accuracy you operate at. The number that governs your real-world false-acceptance rate is not p. It is p compounded over however many attempts you allow, and if you allow unlimited attempts, that number is 1.0. You did not deploy a 95%-accurate gate. You deployed a delay.

Why this is worse than the table suggests

Two objections come up here, and both make the problem worse, not better.

First, the independence assumption. Real attempts are not independent draws — it is the same face, so a model that says “under 16” on one frame will often say it again on the next. True. But this cuts the wrong way once a human is in the loop. Adversarial users do not resubmit the same image; they vary the conditions to find a passing draw. Harsher lighting, a steeper camera angle, makeup, a hat, a few years of apparent age borrowed from an older sibling held just off-frame, a photo of a photo. Every variation is a fresh sample from a distribution the attacker is actively shifting toward the boundary. Non-independence helps you only when the user is passive. The moment they are trying, retries become a guided search for the model’s blind spot, and the effective per-attempt p goes up with each informed retry.

Second, the population. The users with both the motive and the means to grind a retry loop are precisely the near-threshold cohort — the 14- and 15-year-olds — where the model is already weakest. eSafety made this point sharply: platforms that “encouraged self-declared 14- and 15-year-olds to undergo age checks and offered facial age estimation to increase their account age would have been aware that many of them would likely receive a false 16+ outcome.” The retry loophole is not randomly distributed across your users. It concentrates exactly where your check is least reliable and your obligation is highest.

The two failures eSafety actually named

Strip the Australian specifics away and the regulator described two distinct engineering failures, both of which are state-management bugs.

The first is the unbounded retry: a user can re-run the same low-friction method until the dice land right. The second is subtler and arguably worse — platforms were prompting users who had already declared they were under 16 to go take an age check anyway, with no carry-forward of that prior signal. A child who told the platform they were 14 last year got a clean slate and an FAE button this year. That is not a model accuracy problem at all. It is a system that throws away information it already had.

Both failures share a root cause we have written about before: treating the check as an event instead of treating the user’s age as a state. As we argued in our piece on binding age assurance to a person, the check is a momentary event but your obligation is a durable state. A system that stores “ran a check, got 16+” and overwrites it on the next run has no memory. It cannot tell the difference between a user who passed once cleanly and a user who failed nine times and passed on the tenth — and it cannot honor a prior under-16 signal because it never persisted one. Retry abuse is what an amnesiac age gate looks like from the outside.

The attempt-budget: what to actually build

Closing the loophole does not require a better model. It requires treating each verdict as a draw against a budget, and treating the user’s age as sticky state. Six controls do most of the work.

Bound attempts to an identity and a device, not a session. A per-session retry limit is theater; clearing cookies, opening incognito, or reinstalling the app resets it. The budget has to attach to the most stable identifier you have — the account, and a device/hardware signal underneath it — so that the count survives the obvious resets. This is the same binding discipline that defeats proxy and shared-device circumvention; a budget you can wipe is not a budget.

Make results monotonic. A prior “under 16” or “near threshold, uncertain” outcome must not be silently overwritten by a later lucky pass. The safe-by-default state can only be strengthened by a stronger signal (a successful document or chip check), never reversed by a re-roll of the same weak method. If an FAE pass arrives after three FAE near-misses, that is not a pass — it is the predictable tail of a distribution, and your state machine should know it.

Carry the declared age forward. If a user ever told you they were under the threshold, that fact persists and constrains every future check. It does not vanish at the next prompt, and it does not get a fresh trial. This is the exact failure eSafety named, and it is a one-line policy decision before it is an architecture: a declared minor does not get to re-declare their way out.

Escalate on retry instead of re-offering the easy method. The correct response to a failed or borderline attempt is not “try the selfie again.” It is to raise the bar: step up to document plus NFC chip verification or a reusable verified credential, which a 14-year-old cannot grind because they cannot produce the input. Retries should make the gate harder, not give the user another free pull on the same lever. This is the step-up logic that AB 1043-style regimes are pushing toward: low friction for the clear cases, escalating assurance for the uncertain ones.

Widen the buffer at the boundary. Because error rates spike near the line, a result that lands inside a configurable margin of the threshold should not pass — it should route to step-up. Treating “16.2 estimated” as a confident pass is how you absorb the model’s worst-calibrated region into your accept path. A buffer converts the model’s uncertainty into friction for the few rather than a loophole for the determined.

Log every attempt as evidence. Record the attempt count, the method, the conditions, and the outcome for each try — not just the final pass. When an eSafety or Ofcom inquiry arrives, “we verified this user” is a weak answer if the record cannot show how many times they tried first. As we covered in age assurance is now judged on its evidence trail, the defensible artifact is the full sequence: attempts, methods, escalations, and the binding to the account that has used the result since. A regulator who finds a 16+ verdict sitting on top of nine prior failures in your own logs has found your enforcement case for you.

Why vendors ship the loophole anyway

It is worth being honest about why the retry button exists, because the incentive is real and it will not go away on its own. Every retry you deny is a potential abandoned signup, and FAE’s error band cuts both ways — the same near-threshold uncertainty that lets a 14-year-old pass on the tenth try also fails a genuine 22-year-old who photographs young. A hard attempt cap raises the rate at which you wrongly block legitimate adults, and over-blocking is itself a compliance failure under the Australian standard, not a safe default. So product teams reach for the easy release valve: let people try again.

The resolution is not “no retries.” It is escalating retries. A legitimate adult who fails FAE should get a path to prove their age through a stronger method that actually clears them; a minor who fails should hit a wall that the stronger method does not let them climb. Unlimited same-method retries serve neither user well — they just convert your model’s uncertainty into a guaranteed minor pass while still frustrating the adult. The attempt budget is what lets you say yes to the adult and no to the child using the same flow, which is the only version of this that survives an audit.

How Xident handles retry abuse

Xident is built around a verified result that belongs to a person and a state that only moves in the safe direction. The first gate is client-side facial age estimation under liveness, returning a threshold classification — over or under 12, 15, 16, 18, 21, or 25 — rather than a guessed birthday. Results inside the configured buffer never count as a pass: the uncertain band escalates automatically to document OCR, face match, and NFC chip verification, so a near-threshold user does not get to re-roll the selfie. They get routed to a method they cannot grind.

Attempts are bound to the subject and the device through a reusable Xident token, not to a session, so clearing cookies or reinstalling does not hand anyone a fresh budget. A prior under-threshold or uncertain outcome is sticky — it can be strengthened by a stronger check but not overwritten by a later weak pass — which is the monotonic-state property that makes the “roll until you pass” loop dead on arrival. Server-side liveness, blacklist checks, and velocity signals on the Growth and Scale tiers turn rapid repeat attempts into an observable pattern rather than a free path. And because every decision is logged as a classification with its method, assurance level, and attempt history — without storing a date of birth or ID image beyond the check — the trail you hand a regulator shows not just that the user passed, but that they did not have to fail their way there first.


The uncomfortable lesson from Australia’s first three months of enforcement is that the model was rarely the weak point. The platforms that got flagged mostly had access to perfectly capable age estimation. What they shipped around it was a gate with a retry button, no memory of prior declarations, and no budget on attempts — and a probabilistic check with unlimited retries is not a 95% gate. It is a 100% gate pointed the wrong way. The fix is not a better guess at someone’s age. It is refusing to let them keep guessing until your system agrees with the answer they wanted.

Share this article

Ready to implement age verification?

Get started in minutes with our simple SDK. Free trial includes 100 verifications.

Book a 20-minute demo