Simple idea for centralizing the control of the vulnerability-allowlist.yml configuration file
In this post, I’ll share a specific situation I had some time ago and how I went about solving it. It’s a rather niche case, but it may be of interest to those who deal with similar challenges and:
- use GitLab
- use
Container-Scanning.gitlab-ci.yml
GitLab template - want to manage
vulnerability-allowlist.yml
from a single location - …or simply curious what it’s all about
The setup
If you have ever worked with a large GitLab instance, you probably know how managing even simple tasks can become challenging over time. What should be simple enough task may turn into repetitive copy-paste work. I’m no exception. Eventually, I found myself managing groups and projects in GitLab that looked something like this:
.
└──team-group
├── project-with-dockerfiles
├── project-with-ci-templates
├── project0
├── project1
├── project2
└── ... so on ...
Where:
team-group
is the top-level GitLab group for my team.project-with-dockerfiles
is a repository containing all our Dockerfiles. It’s responsible for building container images and pushing them to the GitLab container registry.project-with-ci-templates
holds all our custom GitLab CI job templates.project0
,project1
,project2
, etc. are application repositories that use the images fromproject-with-dockerfiles
viaFROM ...
statements in Dockerfiles, and reuse CI job templates fromproject-with-ci-templates
in their.gitlab-ci.yml
files.... and so on ...
indicates there are many more projects following this same structure.
A shared pipeline is defined in the project-with-ci-templates
repository and included in individual projects using the following configuration (with minor variations across the projects):
include:
- project: "team-group/project-with-ci-templates"
file: "/common-pipeline.yml"
ref: "v1.2.3"
The common-pipeline.yml
file includes the Container-Scanning.gitlab-ci.yml template, which is part of the GitLab Auto-DevOps bundle.
As a result, all projects automatically incorporate the container_scanning
job as part of their pipeline.
Each project generates its own Vulnerability Report based on the scan results.

At the group level, GitLab aggregates vulnerability reports from all projects into a single, compiled view. Starting to see the issue?
The problem
Yes, that’s right. The compiled report at the top-level group includes vulnerabilities from all projects. And that’s perfectly fine. However, there’s a catch.
All projects use base images built in the project-with-dockerfiles
repository. So, if a vulnerability exists in one of those base images, it will naturally appear in any downstream image built from it and thus show up in every project’s report.
This could be acceptable. But in one case, I needed to exclude a well-known vulnerability that the team had reviewed and agreed posed no real risk. Leaving it in there would just create unnecessary noise.
GitLab does allow such exclusions by adding known vulnerabilities to a special file called vulnerability-allowlist.yml
, which must be placed in the root of each project.
Now imagine having to do that manually across tens of projects… Living a dream! That’s why I came up with
The solution
As mentioned earlier, the vulnerability-allowlist.yml
file must be placed in the root directory of each project. In my case, all projects share the same set of base images, so one possible approach was to add the following configuration (see the required data format here) to every project.
generalallowlist:
CVE-XXXX-YY1: package
CVE-XXXX-YY2:
CVE-XXXX-YY3:
But obviously, the next time a similar case arises, I’d need to open merge requests in tens of repositories - far from an ideal solution.
But wait! All projects already use CI templates from team-group/project-with-ci-templates
! So, I took advantage of that and implemented a simple solution. I added a before_script
step to the container_scanning
job in my common-pipeline.yml
(simplified slightly here for clarity). The logic is simple: if the project doesn’t have its own vulnerability-allowlist.yml
in the root, fall back to the one from project-with-dockerfiles
.
container_scanning:
before_script: |
checkout_dir=$(mktemp -d /tmp/checkoutXXXXXX)
if [ ! -e "vulnerability-allowlist.yml" ]; then
git clone https://my.gitlab.instance/team-group/project-with-dockerfiles.git $checkout_dir
cp $checkout_dir/vulnerability-allowlist.yml .
echo "The job will use 'vulnerability-allowlist.yml' file from a 'project-with-dockerfiles' repository."
else
echo "The original 'vulnerability-allowlist.yml' file will be used for this job."
fi
The image used by the container_scanning
job by default is quite minimal - for example, it doesn’t include tools like curl for downloading files. However, since git is available, I just used git clone
instead.
And that’s it! Now, adding a well-known vulnerability to the allowlist can be done in just one place. The time saved can be better spent on more meaningful work.
And that’s all for now. Have a great day!