Update security-triage-automation tool to close linked issues for resolved vulnerabilities
Proposal
When a vulnerability is no longer detected in a project, the status of the vulnerability finding remains unchanged, and any linked issues remain open. To clean this up, we periodically run the security-triage-automation (sta) tool to resolve-and-close all no-longer-detected vulnerabilities.
This sta tool loops through all vulnerabilities for a project whose state is CONFIRMED or DETECTED and:
- If the vulnerability has already been resolved
- Do not process the vulnerability
- Else
-
Resolve the vulnerability, changing its state to
RESOLVED - Close any linked issues
-
Resolve the vulnerability, changing its state to
This process worked fine until the introduction of the Auto resolve vulnerabilities security policy 3 months ago, which executes as the GitLab Security Policy Bot user and periodically loops through all no-longer-detected vulnerabilities and automatically resolves the vulnerability and changes its state to RESOLVED, but does not close linked issues.
Since the sta tool currently only resolves and closes CONFIRMED,DETECTED vulnerabilities, it now always ends up processing 0 vulnerabilities because the GitLab Security Policy Bot has already changed the state of all the vulnerabilities to RESOLVED. However, as mentioned previously, the GitLab Security Policy Bot does not close linked issues, which means we have a large number of vulnerability issues that remain open, as discussed here.
The purpose of this issue is to create an automated process for closing these linked vulnerability issues.
Possible solutions
The best solution to this issue would be to update the GitLab Security Policy Bot to close linked issues when it resolves a vulnerability, however, this is the most complicated approach and the issue tracking this work has yet to be started: Provide option for closing linked issues to Vul... (#545683) • Unassigned • Backlog.
An easier approach would be to implement the following items:
-
Update the
statool to modify the conditional that skips resolved vulnerabilities.If a vulnerability has been resolved, instead of immediately returning, we want to close the linked issues.
-
Update the way the sta tool is invoked so instead of only operating on vulnerabilities whose states are
CONFIRMED,DETECTED, we operate on vulnerabilities whose state isRESOLVED.However, there's a gotcha here. Because there's a massive number of
RESOLVEDvulnerabilities, processing all of them takes an hour forgemnasium:$ git clone git@gitlab.com:gitlab-org/secure/tools/security-triage-automation.git && cd security-triage-automation $ ./main.rb --resolve-and-close --dry-run --custom-labels="group::composition analysis,Category:Software Composition Analysis" --project-path=gitlab-org/security-products/analyzers/gemnasium --log-level=debug --states=RESOLVED 2025-05-21 18:49:06.742310 I Automator -- Notice: Dry run enabled, performing a trial run with no changes made. 2025-05-21 18:49:06.742335 I Automator -- Resolving all no-longer-found vulnerabilities updated on or after 1975-05-21 and closing their linked issues. 2025-05-21 18:49:06.742341 I Automator -- States: ["RESOLVED"] <snip> 2025-05-21 19:48:03.437604 I Automator -- Number of records processed: 5331The majority of the time is spent fetching NVD data because we're forced to wait 0.6 seconds between each call to the NVD API, to avoid being throttled.
Solution 1
We need to fetch NVD data when creating vulnerability issues, however, it's not necessary when simply resolving and closing issues, so we can decrease our processing time substantially by removing the call to fetch NVD data in this case.
This will cut the processing time down from 1 hour to
8 minutes:2025-05-22 10:57:32.351837 I Automator -- Notice: Dry run enabled, performing a trial run with no changes made. <snip> 2025-05-22 11:05:11.324341 I Automator -- Number of records processed: 5331This is the approach we'll implement.
Solution 2
Another solution is to add an
--after=DATEflag that only processes vulnerabilities whoseupdated_atdate is after this date. In other words, it'll stop processing vulnerabilities as soon as it encounters one whoseupdated_atdate is before the--afterdate.For example, if we pass
--after=2024-11-22, and a vulnerability is encountered with anupdated_dateequal to2024-10-31, we'll stop processing at that point, because it's older than the provided--afterdate2024-11-22.This works because this problem only started happening 3 months ago, so we can limit the number of vulnerabilities we need to process by using this flag. This will also avoid needing to fetch every vulnerability using the GraphQL endpoint, thereby reducing resources.
This is the approach we'll implement.see this explanation to understand why we can't implement solution 2.
Implementation Plan
Implement Solution 1 above.
-
Update the statool to modify the conditional that skips resolved vulnerabilities.If a vulnerability has been resolved, instead of immediately returning, we want to close the linked issues.
-
Remove the call to instantiate an NVD object Vulnerability.newis called from Vulnerability.resolve_and_close! -
Bump the version of the statool in the CHANGELOG.md and release a new version. -
Bump the version of the statool in the release project to point to the version released in step3above.We also need to update the way the sta tool is invoked so instead of only operating on vulnerabilities whose states are
CONFIRMED,DETECTED, we operate on vulnerabilities whose state isRESOLVED, to ensure we process and close all the issues that theGitLab Security Policy Botleft open.