Allow MRAP bypass_settings to override protected branch restrictions
What does this MR do and why?
This MR extends the bypass_settings functionality in Merge Request Approval Policies (MRAP) to allow authorized users, groups, roles, or access tokens to bypass both security policy push protection and protected branch restrictions.
Problem
Currently, bypass_settings only bypasses push protection enforced by the security policy itself (via prevent_pushing_and_force_pushing: true), but cannot bypass restrictions configured at the protected branch level (e.g., "Allowed to push and merge" set to "No One"). This creates a confusing user experience where bypass_settings appears to be partially functional.
Solution
When bypass_settings is configured, authorized users/tokens can now push directly to protected branches regardless of the branch's "Allowed to push and merge" configuration, provided they supply a valid security_policy.bypass_reason. This behavior is automatic when bypass_settings is present - no additional configuration is required.
Example configuration:
approval_policy:
- name: Strict Approval Policy
enabled: true
rules:
- type: any_merge_request
branch_type: protected
actions:
- type: require_approval
approvals_required: 2
approval_settings:
prevent_pushing_and_force_pushing: true
bypass_settings:
users:
- id: 123
access_tokens:
- id: 456
Key changes
- BypassSettings class: Updated to support protected branch restriction bypass
- ProtectedBranchBypassChecker: New service that checks if a user is authorized to bypass protected branch restrictions based on security policies
- ProtectedBranchBypassAuditor: New service that logs audit events when protected branch restrictions are bypassed
-
BranchCheck override: Extended
Gitlab::Checks::BranchCheckto skip protected branch checks when bypass is allowed
Security safeguards
- Audit logging: All bypass events are logged with full details including project, user, branch, policy name, and bypass reason
-
Bypass reason required: Users must provide a
security_policy.bypass_reasonpush option - Input sanitization: Bypass reasons are sanitized to prevent XSS
How to test
Setup
- Create a project with a protected branch (e.g.,
main) - Enable
security_policy_protected_branch_bypassfeature flag - Set the protected branch's "Allowed to push and merge" to "No One"
- Create a security policy project and link it to your test project
- Create an approval policy with
bypass_settingsthat includes your test user:approval_policy: - name: Test Bypass Policy enabled: true rules: - type: any_merge_request branch_type: protected actions: - type: require_approval approvals_required: 1 approval_settings: prevent_pushing_and_force_pushing: true bypass_settings: users: - id: <your_user_id>
Test cases
1. Authorized user can bypass with valid reason
git commit --allow-empty -m "Test bypass"
git push -o security_policy.bypass_reason="Emergency hotfix for production issue" origin HEAD:main
Expected: Push succeeds, audit event is logged
2. Authorized user cannot bypass without reason
git commit --allow-empty -m "Test bypass"
git push origin HEAD:main
Expected: Push is rejected with error message requiring bypass reason
3. Unauthorized user cannot bypass even with reason
# As a user NOT listed in bypass_settings
git push -o security_policy.bypass_reason="Trying to bypass" origin HEAD:main
Expected: Push is rejected due to protected branch restrictions
4. Verify audit logging
- Navigate to the security policy project's Secure > Audit events
- Confirm bypass events are logged with user, branch, policy name, and bypass reason
References
Closes #585040
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.