GitLab

## Summary Roll out the `duo_workflow_local_tool_governance` feature flag, which enforces human-in-the-loop AI tool governance rules for GitLab Duo agentic flows on local surfaces (IDE, CLI, Chat). When enabled, local-surface sessions resolve tool permissions against the `local_access` rule column and client-supplied agent privileges are clamped to that governance resolution. Default off; when off, behavior is byte-identical to today (web_access resolution). See https://gitlab.com/gitlab-org/gitlab/-/issues/606343+ for context. Introduced in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/249463+. The confidential security tracker gitlab#606692 can be closed once this flag is enabled. - DRI: @dbernardi - Team Slack channel: `#g_developer_clients` ## What could go wrong? The flip affects all execution modes on local surfaces, not only auto mode. Manual-mode users will silently gain pre-approvals wherever a local allow rule differs from the web rules, and a local deny will block a tool regardless of execution mode. There is also a known fail-open: if governance resolution errors at the JWT-claim mint sites, denied tools resolve to empty (admin denies are dropped) rather than failing closed. This is pre-existing master behavior tracked for the re-key follow-up. Watch Duo workflow error rates and tool-approval metrics on https://dashboards.gitlab.net during each rollout step. ## Blockers before enabling - [ ] Re-key surface selection and the privilege clamp off the server-derived FlowExecutionAuthorizer execution classification (from https://gitlab.com/gitlab-org/gitlab/-/merge_requests/248339+) instead of the client-supplied environment, so the column choice cannot be spoofed. This must land before this flag or `duo_client_executed_flow_governance` or `duo_workflow_background_tool_governance` goes GA. - [ ] Settle the `external` surface split-brain: on master the degraded_surface passthrough reads the `local_access` column on the creation-resolution path while the clamp and JWT mints fall back to web, so the two can resolve against different columns for the same workflow. Decide the intended external-surface behavior and make it consistent before enabling. - [ ] **Row-derived pre-approval intersects the JWT ceiling** (ai-assist!6491 / #608968). With local `ask` rules live, a tool can still be auto-approved through the workflow row, which sits outside the ceiling - so the admin's `ask` wouldn't actually hold. This is the "one gap" I flagged on the epic. - [ ] **Empty or errored governance claim fails closed** (#611843). An empty `tool_access_policies` claim is read as "no ceiling" today, and the mint-side case you already noted above (resolution error -\> empty `denied_tools`) drops admin denies instead of failing closed. Both need to fail closed before we lean on the token to carry local denies. - [ ] **Token bound to its workflow** (#605431). This flag puts local `deny` into the token; while tokens are unbound a permissive one can be replayed onto a governed workflow and that deny is bypassed - so binding needs to be in effect, with client adoption, before the flip. ## Rollout Run all production `/chatops` in [`#production`](https://gitlab.slack.com/archives/C101F3796) and cross-post results to `#g_developer_clients`. **Non-production** ``` /chatops gitlab run feature set duo_workflow_local_tool_governance 50 --actors --dev --pre --staging --staging-ref /chatops gitlab run feature set duo_workflow_local_tool_governance true --dev --pre --staging --staging-ref ``` **Production** — percentage rollout (wait at least 15 min between steps, watch dashboards): ``` /chatops gitlab run feature set duo_workflow_local_tool_governance <percentage> --actors ``` Or target specific actors instead: ``` /chatops gitlab run feature set --group=gitlab-org,gitlab-com duo_workflow_local_tool_governance true /chatops gitlab run feature set --user=dbernardi duo_workflow_local_tool_governance true ``` ## Before global rollout Confirm the relevant gotchas before going to 100%, see [enabling a feature for GitLab.com](https://docs.gitlab.com/development/feature_flags/controls/#enabling-a-feature-for-gitlabcom): - [ ] Both blockers above resolved - [ ] [Docs + version history](https://docs.gitlab.com/development/documentation/feature_flags/) updated - [ ] [Change management issue](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/change-management/#feature-flags-and-the-change-management-process) opened, if required - [ ] [External API consumers](https://docs.gitlab.com/development/feature_flags/#do-not-use-feature-flags-in-external-api-consumers) handled with a fail-open mechanism, if applicable ## Cleanup Remove the flag once [deemed stable](https://handbook.gitlab.com/handbook/product-development/how-we-work/product-development-flow/feature-flag-lifecycle/#feature-flag-lifecycle). Remove the flag and its YAML definition from the codebase, then: ``` /chatops gitlab run release check <merge-request-url> <milestone> /chatops gitlab run feature delete duo_workflow_local_tool_governance --dev --pre --staging --staging-ref --production ``` ## Rollback ``` /chatops gitlab run feature set duo_workflow_local_tool_governance false # production /chatops gitlab run feature set duo_workflow_local_tool_governance false --dev --pre --staging --staging-ref # non-production /chatops gitlab run feature delete duo_workflow_local_tool_governance --dev --pre --staging --staging-ref --production # remove entirely ```

Read the original on gitlab.com ↗