DevOpsLesson
DevOpsLesson

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Stay Updated

Get notified about new tutorials and features.

Tutorials

  • What is DevOps?
  • Docker Tutorial
  • Terraform Tutorial
  • CI/CD Pipeline
  • All Tutorials

Roadmaps

  • DevOps Engineer
  • Cloud Engineer
  • SRE Path
  • All Roadmaps

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 DevOpsLesson. All rights reserved.

DOCKERKUBERNETESTERRAFORMAWSCI/CDLINUXGITDEVOPS ROADMAPCLOUD ROADMAPSRE ROADMAPGIT CHEATSHEETDOCKER CHEATSHEETK8S CHEATSHEETTF CHEATSHEETLINUX CHEATSHEETDOCKERFILE LINTERYAML VALIDATORCRON PARSERREGEX TESTER

Cicd Tutorial

Introduction to CI/CD
Getting Started with GitLab CI/CD
Stages, Jobs, Artifacts & Cache
Variables, Secrets and Environments in GitLab CI
GitLab Runners
GitLab CI Pipeline Rules
GitLab CI Environments
GitLab CI Docker Workflows
GitLab CI Testing
GitLab CI Security Scanning
GitLab CI Deploy to AWS
GitLab CI Multi-Project Pipelines
GitLab CI Best Practices

GitLab CI Security Scanning

PreviousPrev
Next

Learn GitLab CI security scanning with SAST, DAST, secret detection, dependency scanning, container scanning, security reports, and DevSecOps best practices for secure pipelines.

GitLab CI security scanning is one of the fastest ways to bring DevSecOps into a real delivery workflow. Instead of treating security as a separate audit that happens after development is finished, DevSecOps makes security part of the pipeline itself. The same GitLab CI/CD process that builds, tests, and deploys your application can also run static analysis, scan dependencies, inspect container images, detect leaked secrets, and test a running application for common web vulnerabilities.

That approach is often described as shifting security left. The phrase means moving security checks earlier in the software lifecycle, closer to the moment code is written and reviewed. When a vulnerability is discovered during a merge request instead of in production, the cost of fixing it is dramatically lower. The developer still remembers the code change, the blast radius is smaller, and the team can fix the issue before it becomes part of a release.

GitLab is particularly strong here because it does not bolt security onto CI as an afterthought. It provides built-in security analyzers, security report formats, merge request widgets, dashboards, and vulnerability workflows. For teams building modern delivery pipelines, that makes GitLab a practical DevSecOps platform rather than just a CI runner.

What DevSecOps Means in Practice

DevSecOps is not just “run a scanner sometimes.” It is a mindset and an operating model.

In a traditional workflow, development writes code, operations deploys it, and security reviews it near the end. That sequence creates friction. Security findings arrive late, release dates slip, and teams start seeing security as a blocker.

In a DevSecOps workflow:

  • developers receive security feedback during coding and review
  • pipelines automatically enforce baseline controls
  • known vulnerable libraries are detected before release
  • accidentally committed secrets are caught quickly
  • container images are checked before deployment
  • web applications are tested in a running environment
  • security teams get centralized visibility without manually reviewing every commit

This is why “shift left” matters. The earlier a problem is identified, the cheaper it is to fix and the less likely it is to reach customers.

GitLab Built-In Security Scanning Overview

GitLab provides a suite of security scanners and report integrations. Availability depends on your GitLab edition and tier. In general, GitLab Ultimate offers the richest security experience, especially for dashboards, governance, and vulnerability management, while some security capabilities and templates are available on Free or Premium as well.

The major scanners you will see in GitLab CI security scanning are:

  • SAST for source-code level issues
  • Secret Detection for exposed credentials and tokens
  • Dependency Scanning for vulnerable third-party packages
  • Container Scanning for OS and image vulnerabilities
  • DAST for testing a live running application

The important idea is that each scanner looks at a different layer of risk:

  • your code
  • your secrets
  • your dependencies
  • your container base image
  • your deployed runtime behavior

No single scanner covers everything. The value comes from using multiple scanners together.

SAST: Static Application Security Testing

Static Application Security Testing (SAST) analyzes source code without running the application. It looks for risky patterns, unsafe API usage, insecure coding constructs, and common weaknesses such as injection risks, weak cryptography usage, insecure deserialization, or insecure file handling.

Because SAST runs before deployment, it is one of the purest forms of shift-left security. It catches problems while developers are still working in branches and merge requests.

What SAST scans

A GitLab SAST analyzer inspects the code repository and attempts to identify vulnerabilities in supported languages and frameworks. Depending on analyzer support and configuration, it can inspect languages such as:

  • JavaScript and TypeScript
  • Python
  • Java
  • Go
  • Ruby
  • PHP
  • C and C++
  • C# and .NET
  • Kotlin and others, depending on the analyzer set

The exact analyzer selection depends on the project contents. GitLab automatically chooses analyzers based on the repository language and the included SAST template.

How to enable SAST

The simplest way to enable SAST is to include GitLab’s security template:

include:
  - template: Security/SAST.gitlab-ci.yml

That one line is often enough to get an initial scan running. GitLab adds the SAST job definitions for you. In many projects, this is the fastest first win for GitLab DevSecOps adoption.

SAST best practices

To get more value from SAST:

  • run it on merge requests, not only default branch pipelines
  • review findings as part of code review
  • tune exclusions for generated code or vendor folders
  • treat high-confidence findings first
  • combine SAST with dependency and secret scanning for broader coverage

SAST is excellent for code patterns, but it cannot tell you everything about a running system. That is why GitLab security scanning includes other analyzers too.

Secret Detection

One of the most common CI security failures is not a code vulnerability at all. It is a secret that accidentally got committed to Git: an API key, cloud credential, SSH private key, database password, access token, or webhook secret.

Once a secret lands in Git history, the problem is bigger than deleting it from the latest commit. The credential may already have been cloned, logged, mirrored, or exposed in a merge request. The correct response often includes revoking and rotating the secret.

GitLab Secret Detection looks for known secret patterns and high-risk tokens in the repository history or commit content, depending on configuration.

What secret detection catches

Secret detection commonly finds:

  • AWS access keys
  • GitLab or GitHub tokens
  • Slack, Stripe, or Twilio keys
  • generic bearer tokens
  • private keys
  • passwords embedded in config files

How to enable secret detection

Add the template:

include:
  - template: Security/Secret-Detection.gitlab-ci.yml

This makes secret scanning part of the pipeline so developers get early feedback when something sensitive appears in the codebase.

Why this matters

Secret detection is one of the highest-value scanners because it addresses a very common and very dangerous mistake. Even a mature team can accidentally commit a credential. Catching it in CI gives you a chance to stop the merge and rotate the secret before production risk grows.

Dependency Scanning

Modern software depends heavily on open-source libraries. A Node.js application might use dozens or hundreds of transitive packages. A Python service may rely on libraries listed in requirements.txt or poetry.lock. A Java application may pull dependencies through Maven or Gradle. Those libraries save time, but they also introduce supply-chain risk.

Dependency Scanning checks manifest and lock files against vulnerability databases to identify packages with known CVEs or advisories.

What dependency scanning inspects

GitLab dependency scanning can detect vulnerable packages in files such as:

  • package.json and lock files for Node.js
  • requirements.txt, Pipfile.lock, or Poetry files for Python
  • Maven and Gradle descriptors for Java
  • Bundler files for Ruby
  • Composer files for PHP

How to enable dependency scanning

Add the template:

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml

Why dependency scanning matters

You may write secure application code and still ship a vulnerable package. That is why dependency scanning is a core part of GitLab security reports. It helps answer a critical question: Are we pulling in known vulnerable software?

Dependency scanning is also valuable after a merge. New CVEs are published every day. A package that looked fine last month may become high risk today. Running dependency scans regularly helps you spot those changes.

Container Scanning

If your application is built into Docker images, security does not stop at package.json or requirements.txt. The image itself includes an operating system layer, system packages, libraries, and possibly outdated base images.

Container Scanning examines built container images for OS-level and package-level vulnerabilities.

What container scanning checks

Container scanners typically inspect:

  • base image packages such as Alpine, Debian, or Ubuntu packages
  • OS libraries like OpenSSL or glibc
  • vulnerable installed binaries
  • image layer contents relevant to known CVEs

This is especially important when teams use old or unpinned base images. An app can have clean source code and still ship a risky image because the underlying OS layer is outdated.

How to enable container scanning

Add the template:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

You usually also provide the image to scan, often through a variable such as CS_IMAGE.

container_scanning:
  variables:
    CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

DAST: Dynamic Application Security Testing

Dynamic Application Security Testing (DAST) works differently from SAST. Instead of scanning source code, it tests a running application from the outside. In other words, DAST behaves more like an attacker probing the deployed app.

This makes DAST useful for finding issues that appear only when the application is running, such as:

  • exposed HTTP headers
  • authentication flow issues
  • reflected XSS behavior
  • insecure redirects
  • weak TLS or misconfigurations
  • endpoints that behave unsafely under malicious input

What DAST needs

Because DAST scans a live application, it needs a reachable target URL, usually a review app, staging environment, or temporary test deployment.

How to enable DAST

Add the template:

include:
  - template: Security/DAST.gitlab-ci.yml

Then provide a target URL:

dast:
  variables:
    DAST_WEBSITE: https://staging.example.com

When to use DAST

DAST is strongest when you already have:

  • a stable staging or review environment
  • realistic seed data for testing
  • isolated infrastructure so scan traffic does not affect production users

DAST complements SAST. SAST looks at code structure; DAST looks at application behavior.

Enabling Multiple GitLab Security Scanners Together

You can combine security templates in a single .gitlab-ci.yml file:

stages:
  - test
  - security

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml
  - template: Security/DAST.gitlab-ci.yml

variables:
  CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  DAST_WEBSITE: https://staging.example.com

That gives you broad GitLab CI security scanning coverage with minimal YAML.

Reading Security Reports in the Merge Request UI

One of GitLab’s biggest advantages is not just that the scanners run, but that the results are visible where developers already work.

When a merge request pipeline includes security jobs, GitLab can show findings directly in the merge request UI. Reviewers can see whether a branch introduces new vulnerabilities, which scanner reported them, the severity, and often the affected file or dependency.

That improves adoption because developers do not have to leave the review flow and open a separate security tool. The feedback is attached to the change they are reviewing.

In practice, teams often use the MR security widget to:

  • block risky merges
  • understand whether a finding is new or existing
  • prioritize high and critical issues first
  • connect remediation work to the same code review cycle

Security Dashboard and Vulnerability Management

For individual merge requests, the MR widget is enough. For ongoing security operations, you need a broader view. That is where the GitLab Security Dashboard and vulnerability management features matter.

The dashboard helps teams answer questions like:

  • How many open vulnerabilities exist across projects?
  • Which ones are critical?
  • Which findings are new versus previously known?
  • Are we trending in the right direction over time?

This is important because DevSecOps is not just about detection. It is also about triage and remediation. A mature workflow includes:

  1. detecting a finding in CI
  2. classifying severity and confidence
  3. deciding whether it is real and actionable
  4. fixing or mitigating it
  5. tracking it to closure

GitLab vulnerability management helps organize that lifecycle rather than leaving findings buried in job logs.

Failing the Pipeline on Severity Thresholds

Running scans is good. Enforcing policy is better.

Many teams eventually want a rule such as:

  • fail the pipeline if any critical vulnerability is introduced
  • fail on high severity findings in protected branches
  • allow lower severities but require review

There are several ways to enforce that, depending on your GitLab tier and governance model. At a basic level, you can make security jobs required and use merge request approval or policy features. Another practical approach is to add a custom gate job that reads generated report artifacts and exits non-zero when the threshold is exceeded.

A simplified example for SAST might look like this:

security-gate:
  stage: security
  image: alpine:3.20
  needs:
    - job: sast
      artifacts: true
  before_script:
    - apk add --no-cache jq
  script:
    - |
      critical_or_high=$(jq '[.vulnerabilities[] | select(.severity == "Critical" or .severity == "High")] | length' gl-sast-report.json)
      echo "High or critical SAST findings: $critical_or_high"
      test "$critical_or_high" -eq 0

This pattern is powerful because it lets you express a business rule: fail the pipeline only when risk crosses an agreed threshold.

Practical Example: Node.js Project with SAST and Secret Detection

Suppose you have a Node.js API and want a practical first step into GitLab DevSecOps. Start small: enable SAST and Secret Detection.

Here is a sample .gitlab-ci.yml:

stages:
  - install
  - test
  - security

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml

image: node:20

cache:
  key:
    files:
      - package-lock.json
  paths:
    - .npm/

variables:
  npm_config_cache: "$CI_PROJECT_DIR/.npm"

install_dependencies:
  stage: install
  script:
    - npm ci

unit_tests:
  stage: test
  script:
    - npm ci
    - npm test

sast:
  stage: security

secret_detection:
  stage: security

What happens here?

  • GitLab runs your normal Node.js install and test jobs.
  • The SAST template adds a scanner appropriate for the repository contents.
  • The Secret Detection template scans the repository for leaked credentials.
  • Findings appear in GitLab security reports and, when supported by your setup, in the merge request security UI.

From there, you can extend the pipeline with dependency scanning and container scanning. The point is not to build a perfect security program on day one. The point is to start getting security feedback automatically in the same pipeline developers already trust.

Tips for Making GitLab Security Scanning Useful

Teams sometimes enable every scanner and then ignore the results. Avoid that trap.

A better rollout approach is:

  1. start with one or two high-value scanners
  2. make sure the findings are visible in merge requests
  3. decide who triages findings
  4. define a policy for critical and high severity issues
  5. expand coverage over time

Also remember these practical lessons:

  • security jobs should run on merge requests whenever possible
  • use protected variables and masked variables for secrets, not hardcoded credentials
  • keep base images updated so container scanning results stay manageable
  • regularly update dependencies so dependency scanning does not become overwhelming
  • use review or staging environments for DAST instead of production

Final Takeaway

GitLab CI security scanning turns security from a late manual review into an automated part of delivery. SAST checks source code, Secret Detection catches leaked credentials, Dependency Scanning finds vulnerable packages, Container Scanning inspects image layers, and DAST probes a running application. Together, they create a practical DevSecOps workflow that helps teams shift security left without leaving the GitLab pipeline experience.

If you are just getting started, enable SAST and Secret Detection first. Once the team gets comfortable with GitLab security reports, add dependency, container, and dynamic scanning. That step-by-step path is how many strong DevSecOps programs begin.


Knowledge Check

Exercise

Question 1: Shift Left Security

Why is shifting security left important in a GitLab CI pipeline?

Exercise

Question 2: Scanner Purpose

Which GitLab scanner is designed to find accidentally committed API keys, tokens, and private credentials?

Exercise

Question 3: Enabling Scans

What is the simplest way to enable GitLab SAST in a pipeline?

PreviousPrev
Next

Continue Learning

GitLab CI Environments

Learn GitLab CI environments, deployment tracking, review apps, environment URLs, protected environments, deployment approvals, scoped variables, DORA metrics, and a complete multi-environment deployment example.

12 min read·Medium

GitLab CI Docker Workflows

Learn GitLab CI Docker pipelines, per-job and global images, Docker-in-Docker, Kaniko, GitLab Container Registry authentication, Docker Hub pushes, tagging strategies, and a complete build and push example.

14 min read·Medium

GitLab CI Testing

Learn GitLab CI testing, unit tests, JUnit reports, code coverage, coverage badges, cobertura visualization, parallel test execution, CI test variables, and a complete Jest pipeline example.

12 min read·Easy

Explore Related Topics

Do

Docker Tutorials

Build and push Docker images in your pipelines

Gi

Git Tutorials

Trigger CI/CD pipelines from Git events

Try the Tool

YAML Validator

Validate GitHub Actions and CI/CD pipeline YAML files.

Cron Parser

Build and understand scheduled workflow cron expressions.

On This Page

What DevSecOps Means in PracticeGitLab Built-In Security Scanning OverviewSAST: Static Application Security TestingWhat SAST scansHow to enable SASTSAST best practicesSecret DetectionWhat secret detection catchesHow to enable secret detectionWhy this mattersDependency ScanningWhat dependency scanning inspectsHow to enable dependency scanningWhy dependency scanning mattersContainer ScanningWhat container scanning checksHow to enable container scanningDAST: Dynamic Application Security TestingWhat DAST needsHow to enable DASTWhen to use DASTEnabling Multiple GitLab Security Scanners TogetherReading Security Reports in the Merge Request UISecurity Dashboard and Vulnerability ManagementFailing the Pipeline on Severity ThresholdsPractical Example: Node.js Project with SAST and Secret DetectionTips for Making GitLab Security Scanning UsefulFinal TakeawayKnowledge Check