An assertion arrives whose signCount is lower than the value you stored - what do you actually do?
answer
- a signal, never a verdict
- incrementing is only a recommendation
- zero forever means no signal
- it never names which copy
- the specification leaves the response to you
basics
~20 sA signCount regression is a signal that two copies of the private key may exist - never a verdict, and never an identification of which copy is which. Incrementing is only a recommendation on authenticators, so the specification leaves the response to the relying party.
solid answer
~40 sThe authenticator maintains `signCount` and the relying party stores the last value it saw. A returned value less than or equal to the stored one means the sequence has gone backwards, which is consistent with a cloned credential - and equally consistent with a buggy counter or a restored device. The specification is deliberate here: incrementing is a recommendation, plenty of authenticators report zero forever, and a regression does not tell you which of the two copies is the original. So the specification leaves the decision to you: fail the ceremony, or accept it and feed the observation into a risk signal. What you must not do is call it proof, or reject every credential that reports zero - that would lock out entire classes of authenticator.
code
pseudocode · 17 linesnote_sign_count(record, returned):
if returned == 0 and record.sign_count == 0:
return # counter unsupported - no signal at all
if returned > record.sign_count:
record.sign_count = returned # ordinary advance
return
# returned <= stored: the sequence went backwards
record.counter_regressions += 1
record.last_regression_at = now()
risk.observe("webauthn.sign_count_regression", credential = record.id)
if POLICY_FAIL_ON_REGRESSION:
reject("credential may be duplicated") # a policy choice, not a rule
else:
record.sign_count = max(record.sign_count, returned)go deeper
Recall what is being compared: the authenticator sends a counter, the server has the last one it saw, and a value that has not gone up is a hint that two copies of the key may exist. Nothing more is proved.
Explain who owns the counter and why zero is conformant. Be able to say that incrementing is a recommendation rather than a requirement, and that the comparison yields no information when both values are zero.
Show judgment about an ambiguous signal: what you record, what you feed into risk scoring, and whether you fail the ceremony at all given who your users are and how many authenticators they hold. Name the benign causes alongside the malicious one.
Say out loud that this control is best-effort and shrinking, since synchronised credentials exist on more than one device by design. Nothing in the architecture should be load-bearing on it, and the ceremony's real guarantees sit elsewhere.
## What the counter is Inside `authenticatorData` there is a 32-bit `signCount`. The authenticator owns it; the relying party only records the last value it observed on each credential record. The intent is narrow: if an attacker extracts a credential's private key and uses the copy, two devices are now advancing the same sequence independently, and sooner or later a genuine assertion arrives carrying a value the server has already passed. That is the whole of the mechanism, and its limits are written into the specification rather than discovered in the field. ## What a regression means, and what it does not - **It means** the counter you were given is not greater than the one you stored, which is what a second copy of the private key would eventually produce. - **It does not mean** the credential was cloned. A counter that was never properly implemented, an authenticator restored from a backup, a firmware quirk - all produce the same shape. - **It does not tell you which copy is the clone.** Both devices present a valid signature and a plausible counter. The specification says so in as many words, and it is the reason a hard rejection punishes the wrong holder as often as the right one. - **It is not available at all on many credentials.** Incrementing is a recommendation, not a requirement. An authenticator that returns zero on every assertion is conformant, and comparing zero against zero yields nothing. ## What your server actually does 1. **Compare and record.** On every assertion, compare the returned value with the stored one and update the record when it has advanced. 2. **Decide the ceremony's own outcome.** The specification leaves this to you. A quota reporting service where a skipper's only authenticator is a roaming key in a dry bag is not a place to fail a ceremony on an ambiguous signal; somewhere that issues managed authenticators to a small, known population reasonably does. 3. **Persist the observation on the credential record**, not on the session. It is a fact about one credential, and the next assertion from that credential is where it matters. 4. **Let it feed a risk signal.** The scoring itself, and the account-wide response - what is revoked, what the holder is told - is a separate decision from what this one ceremony returns, and it belongs with whoever owns that policy. 5. **Never reject zero.** A credential whose counter never moves is not suspicious, it is ordinary. ## Why the signal is fading The counter was designed for credentials that live on exactly one device. A credential that is backup-eligible and synchronised across a user's devices is, by design, present in more than one place, and the flags in the authenticator data say so. For those credentials a counter of zero is the norm and a meaningful regression is not really available. That is not a defect to work around. It is the honest state of the control, and a senior answer says it plainly: **clone detection through the counter is a best-effort signal on a shrinking subset of credentials**, and no design should be load-bearing on it. If you remove the counter comparison entirely, what is left standing is the challenge, the origin comparison and the signature - which is where the actual security of the ceremony lives. ## Getting the tone right in an interview | a weak answer | a strong answer | |---|---| | a regression proves cloning | a regression is consistent with cloning and with three benign causes | | the lower counter is the clone | neither value identifies the copy | | always fail the ceremony | the specification leaves it to the relying party, and the population decides | | zero means the authenticator is broken | zero is conformant and common, so the signal is simply unavailable | | the relying party increments the counter | the authenticator owns it; the server only records what it last saw | The question is really testing whether a candidate can hold an ambiguous signal without collapsing it into a verdict - which is the same discipline every other probabilistic security signal demands. ## What you write down The record is where this lives, because the comparison is per credential and so is everything you learn from it: - **The last counter you accepted**, and your stated policy for whether a regression updates it. - **A count of regressions and when the last one was**, so a single odd reading is distinguishable from a credential that trips every week. - **Nothing on the session.** A session outlives the ceremony and belongs to an account, while this observation belongs to one credential and is only meaningful the next time that credential is used. With those three in place the on-call conversation at 3 a.m. is short: this credential has regressed once in a year, or eleven times this month, and those are different situations that an unadorned boolean cannot tell apart.
- Should the stored counter be updated after a regression?The specification leaves it to you, and both choices are defensible. Leaving it untouched means the higher value stays as the high-water mark, so a genuine clone keeps tripping the check. Raising it to the returned value silences the signal after one observation. Pick one deliberately and write down why, because the difference is invisible until an incident.
- What is left protecting the ceremony if the counter tells you nothing?The single-use challenge, the expected-origin comparison and the signature over the authenticator data and client-data hash. Those are the load-bearing controls. The counter is a best-effort extra on credentials that live on one device, and it was never what made the ceremony safe.
The counter is an odometer on a credential. If the same car turns up with fewer miles than last time, you have learned that there are probably two cars - not which one is the fake, and not that a fake exists at all, since some odometers never turn.
saying these in an interview costs you the question
- Treats a signCount regression as proof that the credential was cloned
- Believes every authenticator increments the counter on every assertion
- Says the lower counter identifies which copy is the clone
- Rejects all assertions from an authenticator that always reports zero
- Thinks the relying party maintains the counter rather than the authenticator
- Builds a control that only works if the counter is trustworthy