Problem
Approval callbacks currently use GET with token in the URL query string. This causes token leakage through:
- Server and proxy access logs
- Browser history
- Referrer headers
Suggested Changes
- Change the approval action from GET to POST
- Move the token from query string to request header (
X-Aegis-Approval-Token) or form body
- Add one-time token semantics: once an approval is resolved, replay attempts fail
- Serve an HTML confirmation page for browser-click workflows that submits a POST form
Implementation Plan
- Refactor callback handler (
internal/approval/callback.go)
- Keep
GET /callback/approval only for an HTML landing page
- Add
POST handling for the actual state-changing action
- Read token from header or form body, not URL query
- Update notifier payloads (
internal/approval/feishu.go, generic.go, multi.go)
- Change approval links to point to the landing page or direct POST flow
- Update token validation (
internal/approval/store.go)
- Keep HMAC signing, apply only to POST action
- Optionally include timestamp/expiry in signed payload
- Add tests (
internal/approval/callback_test.go)
- Valid POST approve/reject
- Missing token → 403
- Invalid token → 403
- Replay after resolution → fail
Acceptance Criteria
Key Files
internal/approval/callback.go
internal/approval/store.go
internal/approval/feishu.go
internal/approval/generic.go
Problem
Approval callbacks currently use
GETwithtokenin the URL query string. This causes token leakage through:Suggested Changes
X-Aegis-Approval-Token) or form bodyImplementation Plan
internal/approval/callback.go)GET /callback/approvalonly for an HTML landing pagePOSThandling for the actual state-changing actioninternal/approval/feishu.go,generic.go,multi.go)internal/approval/store.go)internal/approval/callback_test.go)Acceptance Criteria
Key Files
internal/approval/callback.gointernal/approval/store.gointernal/approval/feishu.gointernal/approval/generic.go