You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sec(api): approve returns the orphan-preflight 409 before any session or scope check #432
loadApproveExecution (internal/api/handler_purchases.go, around line 563) calls purchase.OrphanExecutionError and returns a 409 right after loading the row, before approvePurchase checks the session, RBAC, or account scope. An unauthenticated or out-of-scope caller who knows an execution ID can tell an orphan non-AWS execution apart from a missing one (409 vs 404), which leaks existence and state. The same ordering is on main; it was not introduced by #381.
Fix: move the orphan preflight after authorization (session scope/RBAC or validated token), as #381 did for the revoke status guard. Add a test that an out-of-scope session with no token gets 404 for an orphan execution, and that an authorized caller still gets the 409.
Closing: this was fixed by #935 (issue #597), which moved the orphan preflight behind authorization.
Checked on current main:
loadApproveExecution no longer calls OrphanExecutionError. The preflight is now rejectOrphanExecution (handler_purchases.go:703), called only at :958, after the session is authorized for the execution. Its doc comment states this ordering. The token path never authorizes an orphan, because an orphan has no per-account contact_email, and ApproveExecution runs the same predicate itself.
handler_purchases_token_oracle_test.go (around :144) covers the orphan state for every caller type. An unauthorized or out-of-scope caller gets the same concealed 404 for an orphan as for a missing execution, and authorized callers still get the 409.
The orphan tests (TestHandler_approvePurchase_{Azure,GCP}OrphanRejects, AWSOrphanFallsThrough, NonOrphanUnchanged) pass on main.
Activity
IAmJSD commentedon Oct 16, 2026
Released: already fixed by #935 (closing, details below)
IAmJSD commentedon Oct 16, 2026
Closing: this was fixed by #935 (issue #597), which moved the orphan preflight behind authorization.
Checked on current main:
loadApproveExecutionno longer callsOrphanExecutionError. The preflight is nowrejectOrphanExecution(handler_purchases.go:703), called only at:958, after the session is authorized for the execution. Its doc comment states this ordering. The token path never authorizes an orphan, because an orphan has no per-accountcontact_email, andApproveExecutionruns the same predicate itself.handler_purchases_token_oracle_test.go(around:144) covers the orphan state for every caller type. An unauthorized or out-of-scope caller gets the same concealed 404 for an orphan as for a missing execution, and authorized callers still get the 409.TestHandler_approvePurchase_{Azure,GCP}OrphanRejects,AWSOrphanFallsThrough,NonOrphanUnchanged) pass on main.