Recovery-key adversarial probe uses a stale setup session #227

Closed
opened 2026-09-27 10:44:45 +00:00 by kayg · 5 comments
Owner

Finding

The recovery key rotation check in tests/adversarial/attack.py expects HTTP 200 from POST /api/v1/auth/recovery/key and reports 403 as a failure. It calls the route with the setup bearer token. The handler requires CurrentUser and a fresh passkey assertion (require_fresh, 5-minute window).

The full adversarial runner executes the 916-request authorization matrix, then the editor attack suite, before attack.py. On this run, that delay exceeded the freshness window. The route returned 403, as required for a stale session; no recovery-key mutation happened. The probe comment says the owner's assertion was made “a moment ago,” but the runner ordering does not preserve that condition under load.

Update the probe to make a fresh account-scoped assertion immediately before rotation (or explicitly expect 403 when stale and separately verify successful rotation with a fresh session). Do not weaken the endpoint's freshness requirement. Evidence: target/tmp/menu-icons-adversarial-latest.log in the menu-icons worktree; relevant route is crates/calternal-auth/src/api.rs::recovery_key.

## Finding The `recovery key rotation` check in `tests/adversarial/attack.py` expects HTTP 200 from `POST /api/v1/auth/recovery/key` and reports 403 as a failure. It calls the route with the setup `bearer` token. The handler requires `CurrentUser` and a fresh passkey assertion (`require_fresh`, 5-minute window). The full adversarial runner executes the 916-request authorization matrix, then the editor attack suite, before `attack.py`. On this run, that delay exceeded the freshness window. The route returned 403, as required for a stale session; no recovery-key mutation happened. The probe comment says the owner's assertion was made “a moment ago,” but the runner ordering does not preserve that condition under load. Update the probe to make a fresh account-scoped assertion immediately before rotation (or explicitly expect 403 when stale and separately verify successful rotation with a fresh session). Do not weaken the endpoint's freshness requirement. Evidence: `target/tmp/menu-icons-adversarial-latest.log` in the menu-icons worktree; relevant route is `crates/calternal-auth/src/api.rs::recovery_key`.
Author
Owner

The post-merge adversarial run for CSP issue #118 also reported recovery key rotation :: unexpected status or key shape: 403. This followed the authorization matrix and editor suite; it matches the stale setup assertion described in #227. The endpoint's fresh-assertion requirement should remain unchanged. The current run's final summary lists this one non-SLOW probe finding alongside SLOW-only latency results.

The post-merge adversarial run for CSP issue #118 also reported `recovery key rotation :: unexpected status or key shape: 403`. This followed the authorization matrix and editor suite; it matches the stale setup assertion described in #227. The endpoint's fresh-assertion requirement should remain unchanged. The current run's final summary lists this one non-SLOW probe finding alongside SLOW-only latency results.
Author
Owner

This worktree's one-round run reproduced the same recovery key rotation :: unexpected status or key shape: 403 result. The probe reached it after the 916-operation authorization matrix and editor probes, so this is consistent with the stale setup session documented here; the server did not accept an unexpected key shape. Full log: target/tmp/phone-chrome-adversarial-retry.log in the phone-chrome worktree.

This worktree's one-round run reproduced the same `recovery key rotation :: unexpected status or key shape: 403` result. The probe reached it after the 916-operation authorization matrix and editor probes, so this is consistent with the stale setup session documented here; the server did not accept an unexpected key shape. Full log: `target/tmp/phone-chrome-adversarial-retry.log` in the phone-chrome worktree.
Author
Owner

Post-merge adversarial run at c2ff7b40: recovery-key rotation returned 403 because the setup assertion was no longer fresh. The dependent configuration probes also received 403 for the same stale assertion, so they did not exercise their payloads. I left the endpoint behavior unchanged.

Post-merge adversarial run at c2ff7b40: recovery-key rotation returned 403 because the setup assertion was no longer fresh. The dependent configuration probes also received 403 for the same stale assertion, so they did not exercise their payloads. I left the endpoint behavior unchanged.
Author
Owner

Already fixed on origin/dev. git log origin/dev --grep='refresh passkey before recovery rotation' shows d6e5989f1. Current tests/adversarial/attack.py calls refresh_owner_assertion() immediately before the authenticated POST /api/v1/auth/recovery/key request, so the probe preserves the route's five-minute freshness requirement. Recommend recording this probe fix and keeping the endpoint freshness check unchanged. Do not close the issue in this audit.

Already fixed on origin/dev. git log origin/dev --grep='refresh passkey before recovery rotation' shows d6e5989f1. Current tests/adversarial/attack.py calls refresh_owner_assertion() immediately before the authenticated POST /api/v1/auth/recovery/key request, so the probe preserves the route's five-minute freshness requirement. Recommend recording this probe fix and keeping the endpoint freshness check unchanged. Do not close the issue in this audit.
Author
Owner

Fixed in d6e5989f1 (origin/dev); the recovery-key probe refreshes its owner assertion before key rotation.

Fixed in d6e5989f1 (origin/dev); the recovery-key probe refreshes its owner assertion before key rotation.
kayg closed this issue 2026-10-03 11:55:24 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#227
No description provided.