Require fresh authorization for high-impact actions #341

Closed
opened 2026-08-08 20:54:26 +00:00 by timmy · 0 comments
Owner

Problem

An authenticated dashboard session can merge pull requests, close assigned issues, revoke a remote device, or revoke every session using only its long-lived session and CSRF proof. Browser confirmation dialogs do not provide server-enforced fresh proof of operator intent.

Vertical slice

Add durable, single-use, short-lived authorization grants bound to the current session, exact action, and exact target. Require a freshly entered operator access secret before high-impact actions. The UI must preserve the pending operation, obtain a grant through an accessible prompt, and retry once.

Acceptance tests

  • Session + CSRF without a grant receives 428 step_up_required before any Gitea or session mutation.
  • Correct reauthentication mints a random grant persisted only as a digest; wrong secrets mint nothing and use existing source throttling.
  • A grant is usable once, for one session/action/target, for at most 90 seconds; replay, expiry, target substitution, and cross-session use fail closed.
  • Parent-session revocation invalidates outstanding grants.
  • Merge, assigned-issue close, remote-device revoke, and sign-out-all enforce the boundary.
  • Mobile/keyboard users get an accessible fresh-authorization prompt; the original merge SHA or action target is retained and retried exactly once.
  • Focused behavioral tests and the full suite pass.

Evidence / non-duplication

src/main.py currently gates mutations at lines 560-570 with session + CSRF only; high-impact routes are around 799, 823, 2104, and 2336. Read-only review of all historical issue titles through #339 and recent commits found session auth, revocation, throttling, and browser boundaries, but no fresh/step-up action authorization. Open issues are assigned to other humans/agents, so none is eligible for Timmy.

## Problem An authenticated dashboard session can merge pull requests, close assigned issues, revoke a remote device, or revoke every session using only its long-lived session and CSRF proof. Browser confirmation dialogs do not provide server-enforced fresh proof of operator intent. ## Vertical slice Add durable, single-use, short-lived authorization grants bound to the current session, exact action, and exact target. Require a freshly entered operator access secret before high-impact actions. The UI must preserve the pending operation, obtain a grant through an accessible prompt, and retry once. ## Acceptance tests - Session + CSRF without a grant receives `428 step_up_required` before any Gitea or session mutation. - Correct reauthentication mints a random grant persisted only as a digest; wrong secrets mint nothing and use existing source throttling. - A grant is usable once, for one session/action/target, for at most 90 seconds; replay, expiry, target substitution, and cross-session use fail closed. - Parent-session revocation invalidates outstanding grants. - Merge, assigned-issue close, remote-device revoke, and sign-out-all enforce the boundary. - Mobile/keyboard users get an accessible fresh-authorization prompt; the original merge SHA or action target is retained and retried exactly once. - Focused behavioral tests and the full suite pass. ## Evidence / non-duplication `src/main.py` currently gates mutations at lines 560-570 with session + CSRF only; high-impact routes are around 799, 823, 2104, and 2336. Read-only review of all historical issue titles through #339 and recent commits found session auth, revocation, throttling, and browser boundaries, but no fresh/step-up action authorization. Open issues are assigned to other humans/agents, so none is eligible for Timmy.
timmy self-assigned this 2026-08-08 20:54:26 +00:00
timmy closed this issue 2026-08-08 21:06:05 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
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: stackchain/stackchain-dashboard#341
No description provided.