Beliebte Suchanfragen

Cloud Native



Agile Methoden



GitLab security scanning – part 2

18.4.2022 | 5 minutes of reading time

… Containers … applications … licenses …

In part 1 of the article series, we focused on static scanning of source code. In this article we will go one step further. First we look at the scanning of (container) images. Then we delve into the topic of DAST by scanning a running container and as a last aspect we will discuss license scanning.

1) Container scanning

So firstly let us look at container scanning. Certainly a topic that has become increasingly important with the use of container orchestration systems such as Kubernetes. As we have seen in part 1 , security scans in GitLab can be enabled in .gitlab-ci.yml by including the appropriate security scan template (lines 25-26). We also add the job build_container_scanning to build a sample image to be scanned (lines 5-18). This job uses Karniko to create the image and pushes the built image into the project’s container registry (lines 6-18). The container scanning template includes the GitLab job container_scanning. In order for this job to find the built image, the job’s CI variable DOCKER_IMAGE must be overwritten (lines 21-23).

2 - build
3 - test
5# Job to build and push image to registry
7  stage: build
8  image:
9    name:
10    entrypoint: [""]
11  script:
12    - mkdir -p /kaniko/.docker
13    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
14    - |
15      /kaniko/executor --context $CI_PROJECT_DIR \
16                       --dockerfile ${CI_PROJECT_DIR}/container-scanning/Dockerfile \
17                       --destination $CI_REGISTRY_IMAGE:container-latest \
18                       --build-arg VERSION=$CI_COMMIT_TAG
20# Modify variable DOCKER_IMAGE of job container_scanning to match correct image has been pushed in build job
22  variables:
23    DOCKER_IMAGE: "${CI_REGISTRY_IMAGE}:container-latest"
26  - template: Security/Container-Scanning.gitlab-ci.yml

The image provides a simple HTTP server written in Python. Pushing the code starts the pipeline. After the image is built, GitLab checks it:
Note that the scan job runs in the Test stage. This is defined in job container_scanning of the container scanning template.

As a first result we can look at the output of the job. There we see that the log of the scanner Trivy is used. Alternatively, GitLab uses Grype to scan containers. Moreover, we are able to browse or even download the results as JSON-formatted files.

Finally, all vulnerabilities are listed in the security tab of the pipeline. And as soon as the branch is merged into the default branch, they are also listed in the Security Dashboard and Vulnerability Report.

2) Dynamic application security testing (DAST)

After the static analysis of a container, we now want to scan a running application during pipeline execution. Therefore GitLab makes dynamic application security scanning available to developers. For this we use GitLab Services within the pipeline to represent an endpoint of the application. That means GitLab runs a Docker image during a job and provides a URL defined by an alias to access that application. Here the job dast is extended by a service linked to a running container (lines 27-31). Similar to point one, the job build_dast creates a sample image which provides an endpoint to be scanned (lines 5-19) based on a simple Python HTTP server.

2  - build
3  - dast
5# Job to build and push image to registry
7  stage: build
8  image:
9    name:
10    entrypoint: [""]
11  script:
12    - mkdir -p /kaniko/.docker
13    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
14    - |
15      /kaniko/executor --context $CI_PROJECT_DIR \
16                       --dockerfile ${CI_PROJECT_DIR}/dast/Dockerfile \
17                       --destination $CI_REGISTRY_IMAGE:dast-latest \
18                       --build-arg VERSION=$CI_COMMIT_TAG
21  - template: DAST.gitlab-ci.yml
23# Set DAST environment
27# Extend included dast job by a service to connect dast to built image
29  services: # use services to link your app container to the dast job
30    - name: $CI_REGISTRY_IMAGE:dast-latest
31      alias:

As a further step, the address of the endpoint must be passed to the DAST job. This is done in the variable DAST_WEBSITE: (lines 23-25).

Committing any code will start two jobs:

Again all found vulnerabilities are listed in the security tab of the pipeline and, as soon as the branch is merged into the default branch, at the vulnerability report as well.

More in-depth information about any vulnerabilities can be found by clicking the entries of the overview table. There you will get additional information such as links to CVEs, scanners used and a more detailed description of the appropriate vulnerability.

3) License scanning

So far, the term security scanning has always been associated with the scanning of source code. However, license compliance looks less at the source code itself and more at the licenses of integrated software packages. License compliance is the process that ensures that a company only uses software packages that it is allowed to use. This process is intended to prevent unbudgeted costs from arising, for example from the use of unlicensed software. Another use case would be to only use software for projects whose license model is compatible with the company’s own guidelines.
LicenseFinder determines the license of software packages. Furthermore, GitLab allows you to create Deny and Allow lists to automatically detect incompatible licenses. If such licenses are detected, an approval must be issued manually.

Again we use Python to take a closer look at the implementation of license scanning. Python maintains dependencies in a file called requirements.txt. After enabling license scanning in .gitlab-ci.yml

2  - template: Security/License-Scanning.gitlab-ci.yml

and pushing the following requirements.txt to the project’s root directory


GitLab starts the license scanning job:

Furthermore, the results are available in various places, among others:

  1. at the pipeline’s page on the Licenses tab
  2. at the overview page of the corresponding merge request

Unfortunately, it is not yet possible to create license policies before the merge into the default branch. Therefore first merge the branch into the default branch. As of now, the license compliance page displays all licenses. And secondly now GitLab allows developers to prohibit or explicitly allow individual software licenses for a project via license policies. As you can see in the following screenshot, a deny policy of the “MIT License” is created.

As soon as license policies are created, the license compliance page reports the current state of all used licenses.

Summing up

In addition to static security scanning based on code (GitLab security scanning – part 1 ), GitLab also provides other scanning methods such as container, application and license scanning. When working with container orchestration systems like Kubernetes, the three aspects covered in this post can make an important contribution when securely deploying an application.

share post




More articles in this subject area

Discover exciting further topics and let the codecentric world inspire you.


Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.