Scan result policy blocking MR when vulnerabilities do not match the fix_available criteria defined in the policy
Summary
With testing newly introduced scan result policy filters to support age based filtering of detected vulnerabilities, I've noticed some unexpected behavior. An MR is being blocked when it should not be.
Steps to reproduce
-
I started by ensuring I could implement dependency scanning and detect results using a typical policy that blocks MRs based on the severity match (Critical, High, Medium). This I used as a baseline to ensure I could produce a High and Medium finding based on this guide. It took some time to properly produce the results, so days passed to have enough time to get this test in place, during which it's possible these findings were detected on some non-default branches.
-
Next, I created policies using the age filter:
Policy yaml
type: scan_result_policy
name: Block DS Vulnerabilities (Reduced Noise)
description: >-
- Block MRs with Critical severity vulns
- Set an SLA of 30 days for High severity vulns
- Set an SLA of 60 days for Medium severity vulns
- Ignore false positives and dependency scanning findings with no fix
available
enabled: true
rules:
- type: scan_finding
scanners:
- dependency_scanning
vulnerabilities_allowed: 0
severity_levels:
- critical
vulnerability_states: []
branch_type: default
vulnerability_attributes:
false_positive: false
fix_available: false
- type: scan_finding
scanners:
- dependency_scanning
vulnerabilities_allowed: 0
severity_levels:
- high
vulnerability_states:
- detected
- confirmed
- dismissed
- resolved
branch_type: default
vulnerability_age:
operator: greater_than
value: 1
interval: day
vulnerability_attributes:
fix_available: false
false_positive: false
- type: scan_finding
scanners:
- dependency_scanning
vulnerabilities_allowed: 0
severity_levels:
- medium
vulnerability_states:
- detected
- confirmed
- dismissed
- resolved
branch_type: default
vulnerability_age:
operator: greater_than
value: 2
interval: day
vulnerability_attributes:
fix_available: false
false_positive: false
actions:
- type: require_approval
approvals_required: 1
role_approvers:
- developer
- maintainer
- owner
- In my scenario, I first set the policy to 30 days for High severity and 60 days for Medium. The results in the MR were as expected - a High and Medium severity finding were detected but approval was NOT required.
- I then narrowed the criteria down to 1 and 2 days respectively so I could demo this more quickly and observe the policy behaving properly. However, when I reran the job on the MR, it completed and showed a policy violation, that one of these findings must have a
detecteddate greater than 1 or 2 days. This is not expected as I have yet to merge these changes into the default branch in any experiments. It's possible that these findings have beendetectedon a non-default branch more than 1 or 2 days prior to the day I tested and observed this behavior. However, the Vulnerability report does not show the detected CVEs as appearing on the default branch. We may want to clarify what exactly the age criteria is based on. Below is the current Vuln Report:
If we are setting the age SLA based on the datetime at which the vulnerability is first Detected on the default branch (which is expected), I would also expect this vuln to appear in the Vulnerability Report
- Note that I enforce Dependency Scanning to run using an SEP triggered on
*branches.
Example Project
What is the current bug behavior?
Described above.
What is the expected correct behavior?
The MR should not be blocked unless we can see a vulnerability appearing on the default/target branch and the detected date is greater than the specified policy vulnerability age.
Relevant logs and/or screenshots
Output of checks
Results of GitLab environment info
Expand for output related to GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of: `sudo gitlab-rake gitlab:env:info`) (For installations from source run and paste the output of: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
Results of GitLab application Check
Expand for output related to the GitLab application check
(For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:check SANITIZE=true)(For installations from source run and paste the output of:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)(we will only investigate if the tests are passing)
Implementation Plan
-
backend Update Security::Findingfix_availableandno_fix_availablescopes to considerfinding_data->solution
scope :fix_available, -> do
where(
"jsonb_array_length(finding_data -> 'remediation_byte_offsets')::bigint > 0
OR finding_data -> 'solution' IS NOT NULL"
)
end
scope :no_fix_available, -> do
where(
"finding_data -> 'remediation_byte_offsets' IS NULL
OR jsonb_array_length(finding_data -> 'remediation_byte_offsets')::bigint <= 0
OR finding_data -> 'solution' IS NULL"
)
end
Verification Steps
- Create a project with container scanning on a vulnerable image. Eg .gitlab-ci.yml:
include:
- template: Security/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_IMAGE: 'citizenstig/dvwa:latest'
- Create a scan result policy to require approval when a fix is available
type: scan_result_policy
name: Fix Available
description: ''
enabled: true
rules:
- type: scan_finding
scanners: []
vulnerabilities_allowed: 0
severity_levels: []
vulnerability_states:
- detected
- confirmed
- dismissed
- resolved
branch_type: protected
vulnerability_attributes:
fix_available: true
actions:
- type: require_approval
approvals_required: 1
group_approvers_ids:
- <>
- Create a MR that updates README and verify that the approval is required
