Create separate audit events for security policy violations in merge requests
What does this MR do and why?
Previously we were creating one audit event for all security policy violations in a merge request scoped to the target project.
However, the goal of the security policy audit events is to scope the audit events to the security policy project for easier tracking of security policy violations by admins. For this reason, we need to create separate audit events for each violations scoped to the security policy project.
If there are multiple violations from the same security policy though, we are groping them in the same event to reduce noise while providing comprehensive audit events.
References
See this discussion for more details: #539231 (comment 2611008089)
Screenshots or screen recordings
How to set up and validate locally
-
Enable the feature flag in the Rails console:
Feature.enable(:collect_security_policy_violations_detected_audit_events) Feature.enable(:collect_merge_request_merged_with_policy_violations_audit_events) -
Switch to admin mode and set up the audit event streaming
- Doc: https://docs.gitlab.com/administration/compliance/audit_event_streaming/#add-a-new-http-destination
- Localhost path: http://gdk.test:3000/admin/audit_logs?tab=streams
- HTTP Listener: https://pipedream.com/ OR https://gitlab.com/imam_h/webhook-inbox
- Set up a project with security policies:
- Configure an MR Approval Policy. Example
- Make sure the pipeline has required scanners either through Scan execution policies or in gitlab-ci.yml
- Create a merge request that violates the policy:
- Example
- Wait for policy evaluations; PolicyBot will post a comment with the violation details
- Verify an audit event with type
policy_violations_detectedis received in the streaming destination - Merge the merge request with security policy violation
- Verify an audit event of type
merge_request_merged_with_policy_violations- Both in streaming destination and in the security policy project
- If there is multiple violations belonging to a different security policies from different SPPS, the audit event is created in the source SPP
`policy_violations_detected` event json
{
"id": "83cf735d-498d-4693-bffe-0f640eef9dbb",
"author_id": 1,
"entity_id": 24,
"entity_type": "Project",
"details": {
"merge_request_title": "Edit .env",
"merge_request_id": 373,
"merge_request_iid": 53,
"source_branch": "root-main-patch-40660",
"target_branch": "main",
"project_id": 24,
"project_name": "Project 3",
"project_full_path": "gitlab-org/project-3",
"violation_status": "failed",
"violation_data": {
"context": {
"pipeline_ids": [
1024
],
"target_pipeline_ids": [
987
]
},
"violations": {
"scan_finding": {
"uuids": {
"newly_detected": [
"1c65afa8-27b9-55f2-8085-c4955463d13e"
]
}
}
}
},
"event_name": "policy_violations_detected",
"author_name": "Administrator",
"author_class": "User",
"target_id": 517,
"target_type": "Security::Policy",
"target_details": "Security Policy",
"custom_message": "Security policy violation(s) is detected in merge request (gitlab-org/project-3!53)",
"ip_address": "192.168.178.48",
"entity_path": "gitlab-org/project-3"
},
"ip_address": "192.168.178.48",
"author_name": "Administrator",
"entity_path": "gitlab-org/project-3",
"target_details": "Security Policy",
"created_at": "2025-07-10T11:50:04.785Z",
"target_type": "Security::Policy",
"target_id": 517,
"event_type": "policy_violations_detected"
}
`merge_request_merged_with_policy_violations` event json
{
"id": 2130,
"author_id": 2,
"entity_id": 24,
"entity_type": "Project",
"details": {
"merge_request_title": "Edit README.md",
"merge_request_id": 374,
"merge_request_iid": 54,
"source_branch": "root-main-patch-91168",
"target_branch": "main",
"project_id": 24,
"project_name": "Project 3",
"project_full_path": "gitlab-org/project-3",
"violation_status": "warn",
"violation_data": {
"errors": [
{
"error": "ARTIFACTS_MISSING"
}
],
"context": {
"pipeline_ids": [
1025
],
"target_pipeline_ids": [
1033
]
}
},
"merged_at": "2025-07-10T11:53:50.740Z",
"policy_approval_rules": [
{
"name": "Security Policy",
"report_type": "license_scanning",
"approvals_required": 0,
"approved": true,
"approved_approvers": [
"rivka"
],
"invalid_rule": false,
"fail_open": true
}
],
"event_name": "merge_request_merged_with_policy_violations",
"author_name": "Olinda Morissette",
"author_class": "User",
"target_id": 517,
"target_type": "Security::Policy",
"target_details": "Security Policy",
"custom_message": "Merge request (gitlab-org/project-3!54) was merged with security policy violation(s)",
"ip_address": "172.16.123.1",
"entity_path": "gitlab-org/project-3"
},
"ip_address": "172.16.123.1",
"author_name": "Olinda Morissette",
"entity_path": "gitlab-org/project-3",
"target_details": "Security Policy",
"created_at": "2025-07-10T11:53:52.780Z",
"target_type": "Security::Policy",
"target_id": 517,
"event_type": "merge_request_merged_with_policy_violations"
}
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.
Related to #539231 (closed)
