Skip to content

Fix ScheduleFlow missing CheckIfCanStartFlow authorization#1161

Open
Alearner12 wants to merge 1 commit intogoogle:masterfrom
Alearner12:fix-scheduleflow-admin-auth
Open

Fix ScheduleFlow missing CheckIfCanStartFlow authorization#1161
Alearner12 wants to merge 1 commit intogoogle:masterfrom
Alearner12:fix-scheduleflow-admin-auth

Conversation

@Alearner12
Copy link
Copy Markdown

Title: Fix missing CheckIfCanStartFlow authorization check in ScheduleFlow

Description

This PR addresses the authorization bypass described in Issue #1160

The ScheduleFlow method in ApiCallRouterWithApprovalChecks was previously missing the CheckIfCanStartFlow and CheckClientAccess authorization checks that are correctly enforced in the corresponding CreateFlow method.

Because CheckIfCanStartFlow is the sole API-layer enforcement point for RESTRICTED_FLOWS, its omission allowed non-admin users to schedule restricted flows like ExecutePythonHack or LaunchBinary, bypassing the intended authorization boundary.

This PR adds the missing checks to ScheduleFlow and includes the corresponding unit test assertions in api_call_router_with_approval_checks_test.py.

Verification / Testing

Tested locally against a GRR docker instance using ApiCallRouterWithApprovalChecks.

Before Fix (ScheduleFlow missing check):
A non-admin user (analyst) attempting to schedule ExecutePythonHack successfully bypasses the API router and reaches the DB handler (the 500 error below is a DB FK constraint error, proving it bypassed the API auth ACLs):

$ curl -s -u analyst:analyst123 -H "x-csrftoken: $CSRF" ... -X POST http://localhost:8000/api/v2/clients/C.1234567890abcdef/scheduled-flows -d '{"flow":{"name":"ExecutePythonHack","args":{}}}'

HTTP/1.1 500 Internal Server Error
)]}'
{"message": "Client with id 'C.1234567890abcdef' does not exist: (1452, 'Cannot add or update a child row... FOREIGN KEY...)"}

After Fix (Checks Added):
The same request from the non-admin user is now correctly blocked at the router level by the ACL, matching the exact behavior of CreateFlow:

$ curl -s -u analyst:analyst123 -H "x-csrftoken: $CSRF" ... -X POST http://localhost:8000/api/v2/clients/C.1234567890abcdef/scheduled-flows -d '{"flow":{"name":"ExecutePythonHack","args":{}}}'

HTTP/1.1 403 Forbidden
)]}'
{"message": "Access denied by ACL: No approval found.", "subject": "aff4:/C.1234567890abcdef"}

Related Issues

Fixes #1160

@google-cla
Copy link
Copy Markdown

google-cla bot commented Mar 30, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@Alearner12 Alearner12 force-pushed the fix-scheduleflow-admin-auth branch from 4379edd to fc58038 Compare March 30, 2026 16:20
@Alearner12
Copy link
Copy Markdown
Author

@googlebot I signed it!

args: api_flow_pb2.ApiCreateFlowArgs,
context: Optional[api_call_context.ApiCallContext] = None,
) -> api_flow.ApiScheduleFlowHandler:
self.approval_checker.CheckClientAccess(context, args.client_id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that defeats the whole purpose of ScheduleFlow (allowing users that do not have access to the client yet to schedule something for the future), no? Or am I missing something here?

@Alearner12 Alearner12 force-pushed the fix-scheduleflow-admin-auth branch from fc58038 to 232d8db Compare March 31, 2026 07:59
@Alearner12
Copy link
Copy Markdown
Author

@panhania You are 100% correct about CheckClientAccess, apologies for that! By enforcing that check, I broke the ability to schedule flows without already having active approval, which completely defeats the purpose of the scheduling feature. I’ve just updated the PR to remove that line.

However, the vulnerability here is the missing CheckIfCanStartFlow check.

Without CheckIfCanStartFlow acting as a gatekeeper at the router level, a standard non-admin analyst can easily schedule admin-only restricted flows like ExecutePythonHack or LaunchBinary. Once a manager grants a routine client approval later a workflow where scheduled payloads aren't surfaced for review that restricted payload automatically executes with SYSTEM privileges on the endpoint, bypassing the admin enforcement entirely.

To prevent this privilege escalation, ScheduleFlow must still allow users to schedule standard flows without active client approval, but absolutely prevent non-admins from scheduling RESTRICTED_FLOWS.

I've pushed an update to the PR removing the CheckClientAccess requirement but keeping the CheckIfCanStartFlow admin enforcement. Let me know if that makes sense

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ScheduleFlow missing CheckIfCanStartFlow authorization check (privilege escalation)

2 participants