Skip to content

sec(auth): enforce per-permission Constraints on execute-any/own, approve-any/own, runPlanned (SEC-01 follow-up to #1210) #60

Description

@cristim

Problem

PR LeanerCloud/cloud-commitments-cli#1210 fixes SEC-01 (issue LeanerCloud/cloud-commitments-cli#1141) for execute:purchases and execute:ri-exchange by enforcing per-permission Constraints (MaxPurchaseAmount, Providers, Services, Regions, AccountIDs) at execution time. The same fail-open class still exists on the sibling money-spending verbs whose constraints are also silently ignored:

  1. execute-any:purchases / execute-own:purchases — Handler.authorizeSessionExecuteDirect (internal/api/handler_purchases.go:792) gates the direct-execute path with a bare HasPermissionAPI(action=execute-any, resource=purchases) / HasPermissionAPI(action=execute-own, ...) check. If the granting permission carries Constraints (e.g. MaxPurchaseAmount: $500, Providers: [aws]), they are not evaluated. A user who satisfies the upstream execute:purchases constraint set (PR fix(auth): enforce per-permission constraints on execute paths cloud-commitments-cli#1210) but whose execute-any:purchases is capped tighter can still direct-execute past the tighter cap.
  2. approve-any:purchases / approve-own:purchases — Handler.authorizeSessionApprove (internal/api/handler_purchases.go:592) gates session-approve via the bare verb check. approvePurchaseViaSession then calls purchase.Manager.ApproveAndExecute which synchronously fires the AWS purchase (internal/api/handler_purchases.go:572); the approve path is also an execute path, but the approve permission's Constraints aren't enforced.
  3. runPlannedPurchase (internal/api/handler_purchases.go:306) calls requirePermission("execute", "purchases") then transitions the planned execution to running without consulting Constraints against the persisted recommendations. A user who runs a plan they didn't create (via update-any:purchases) bypasses any Constraints on their own execute:purchases permission.

All three are the same fail-open class PR LeanerCloud/cloud-commitments-cli#1210 fixed for the web execute path: a bare verb gate runs, the matcher's nil request-side constraints short-circuit checkPermissionConstraints to allow, and the configured caps are silently ignored on a money-mutation path.

Fix sketch

Apply the same requirePermissionConstraints pattern PR LeanerCloud/cloud-commitments-cli#1210 introduced:

  • For execute-any / execute-own: build the same per-rec constraint sets as purchaseConstraintSets in validateExecutePurchaseRequest and call requirePermissionConstraints(session, "execute-any" or "execute-own", "purchases", sets) inside authorizeSessionExecuteDirect once the verb branch is chosen.
  • For approve-any / approve-own: in authorizeSessionApprove, after the verb branch is chosen, re-hydrate the execution's recommendations and build purchaseConstraintSets against them before allowing ApproveAndExecute to fire.
  • For runPlannedPurchase: re-hydrate the planned execution's recommendations and call requirePermissionConstraints(session, "execute", "purchases", purchaseConstraintSets(...)) before the pending|paused → running transition. Same shape as the web execute path.

Regression tests should mirror the SEC-01 ones in TestHandler_executePurchase_PermissionConstraintsDenied: a session that passes the bare verb gate but whose constraints reject the request returns 403 before any state mutation / SDK call.

Triage

type/security, priority/p1, severity/high, urgency/soon, impact/all-users, effort/m, triaged. Same severity as the parent SEC-01: a constrained purchaser can spend past their configured cap via the unfixed verb on a money path.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions