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.
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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
authenticatethat refuses a revoked device still holding a livetoken, the one whose comment cites audit M2.
Two tests do cover revocation and one says it is exercising the
retirement path. Both call
poll, andpollcarries its owndevice_revokedguard on the device row, so both pass whether or notauthenticaterefuses anything. Theauthenticatecheck is what everyother 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 itsown, 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.pyships the harness. The four that died are realcoverage: proof signature, clock skew, replay admission and device key
mismatch.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
assigned to @paulhitt
mentioned in commit
e2fb99a47d