Restrict policy bot to least privilege permissions
What does this MR do and why?
Restricts the security policy bot to least privilege permissions using prevent_all with explicit exceptions.
Background
The security policy bot is added as a guest member to projects, but it should only have the specific permissions required for its functionality (running security scans, managing vulnerabilities). Previously, the bot inherited all guest permissions, which violates the principle of least privilege.
This MR was created as an alternative to !232637 (closed), which explored using MINIMAL_ACCESS role for the bot. That approach required significant changes across 21 files because MINIMAL_ACCESS is only valid for group members, not project members.
After discussion with @jayswain and @imand3r, we decided the prevent_all approach is cleaner
How it works
-
Enable explicit permissions: The bot gets only permissions defined in
config/authz/roles/security_policy_bot.yml:build_download_codecreate_bot_pipelinecreate_on_demand_dast_scancreate_pipelinecreate_vulnerability_state_transitionread_on_demand_dast_scan
-
Prevent everything else: Using
prevent_allwithexcept, we block all other permissions the bot would inherit from guest membership. -
Exception for conditional permissions:
read_buildand_read_public_buildare excepted fromprevent_allso other policy rules (e.g., public build visibility) can still control when they're granted.
Trade-off
The UI still shows "Guest" role for the bot in the members page, even though it has different permissions.
References
- Supersedes: !232637 (closed) (MINIMAL_ACCESS approach)
- Related discussion: !232637 (closed) (comment 3275515581)
- Parent issue: #594741 (closed)
How to set up and validate locally
-
Create a security policy bot and add as guest to a project:
bot = User.find_by(user_type: :security_policy_bot) project = Project.find(<id>) project.add_guest(bot) -
Verify permissions are restricted:
policy = ProjectPolicy.new(bot, project) # Should be ALLOWED (from YAML role): policy.allowed?(:create_pipeline) # => true policy.allowed?(:build_download_code) # => true # Should be PREVENTED (guest permissions blocked): policy.allowed?(:create_issue) # => false policy.allowed?(:read_wiki) # => false policy.allowed?(:upload_file) # => false
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.