Gate Duo CLI via request header instead of client-trusted param

What does this MR do and why?

The Duo CLI admin gate previously fired only when the client sent requires_duo_cli_enabled: true in the create-workflow request body — so any client that omitted it (older CLIs, or a modified client) walked straight past an admin's "Duo CLI off" setting.

This MR makes the server the source of truth. It removes the client-trusted param and identifies a Duo CLI session from the X-Gitlab-Client-Name: Duo CLI header the CLI already sends on every request. A Duo CLI session — interactive or headless alike — is blocked whenever the duo_cli_enabled_setting FF is on and the duo_cli_enabled admin setting is off, regardless of request body. A duo_cli_session_blocked audit event is emitted on refusal.

GA-readiness change for Duo CLI gating. Companion client MR: gitlab-org/editor-extensions/gitlab-lsp!3596 (merged). (FF default-flip for self-managed is a separate MR.)

Honest-actor model (intentional): the client-name header is client-set and forgeable — governance for honest admins, not a security boundary.

Where to look

  • ee/lib/api/ai/duo_workflows/workflows.rb — the gate in the post block reads if duo_cli_request? && duo_cli_disabled_by_admin? (the CLI-request check is the explicit outer guard; duo_cli_disabled_by_admin? is just the FF + admin-setting check). :requires_duo_cli_enabled removed.
  • config/audit_events/types/duo_cli_session_blocked.yml — new audit event type.
  • doc/user/compliance/audit_event_types.md — regenerated to match (do not hand-edit).
  • ee/spec/requests/api/ai/duo_workflows/workflows_spec.rb — header-based gating cases; interactive and headless are gated identically.

References

Screenshots or screen recordings

N/A — no UI changes (API gating only).

How to set up and validate locally

  1. Enable the FF and disable the CLI in the Rails console:
    Feature.enable(:duo_cli_enabled_setting)
    Ai::Setting.instance.update!(duo_cli_enabled: false)
  2. CLI blockedPOST /api/v4/ai/duo_workflows/workflows with header X-Gitlab-Client-Name: Duo CLI403 "Duo CLI has been disabled by your administrator" and a duo_cli_session_blocked audit event. A headless run is blocked the same way (no exemption).
  3. Non-CLI unaffected — same request without the X-Gitlab-Client-Name: Duo CLI header ⇒ succeeds.
  4. Re-enable (duo_cli_enabled: true) ⇒ the CLI request succeeds again.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Edited by Malte Heuser

Merge request reports

Loading