Revocation is tested off the inbox, where it was not #216

Merged
paulhitt merged 1 commits from test/revocation-is-tested-off-the-inbox into main 2026-09-22 17:10:28 +00:00
paulhitt commented 2026-09-22 15:08:06 +00:00 (Migrated from gitlab.com)

Five refusals in the auth path were disabled one at a time to see which
the suite noticed. Four died. This one survived all 736 tests: the check
in authenticate that refuses a revoked device still holding a live
token, the one whose comment cites audit M2.

Two tests do cover revocation and one says it is exercising the
retirement path. Both call poll, and poll carries its own
device_revoked guard on the device row, so both pass whether or not
authenticate refuses anything. The authenticate check is what every
other authenticated route relies on, and nothing touched it.

With it gone a revoked phone keeps fetching bundles, sending, replenishing
prekeys and mutating groups until its token expires. Only its inbox
closes.

The test goes through bundles, which has no revocation check of its
own, and asserts the target's one-time prekey is still in the pool
afterwards, so the refusal is shown to happen before the route does any
work.

Scripts/mutate.py ships the harness. The four that died are real
coverage: proof signature, clock skew, replay admission and device key
mismatch.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Five refusals in the auth path were disabled one at a time to see which the suite noticed. Four died. This one survived all 736 tests: the check in `authenticate` that refuses a revoked device still holding a live token, the one whose comment cites audit M2. Two tests do cover revocation and one says it is exercising the retirement path. Both call `poll`, and `poll` carries its own `device_revoked` guard on the device row, so both pass whether or not `authenticate` refuses anything. The `authenticate` check is what every other authenticated route relies on, and nothing touched it. With it gone a revoked phone keeps fetching bundles, sending, replenishing prekeys and mutating groups until its token expires. Only its inbox closes. The test goes through `bundles`, which has no revocation check of its own, and asserts the target's one-time prekey is still in the pool afterwards, so the refusal is shown to happen before the route does any work. `Scripts/mutate.py` ships the harness. The four that died are real coverage: proof signature, clock skew, replay admission and device key mismatch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-22 15:08:06 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-22 17:10:28 +00:00 (Migrated from gitlab.com)

mentioned in commit e2fb99a47d

mentioned in commit e2fb99a47d6b914f88a22133c454b4b44d58757d
paulhitt (Migrated from gitlab.com) merged commit e2fb99a47d into main 2026-09-22 17:10:28 +00:00
Sign in to join this conversation.