Over ten sessions we wired six security tools into a GitLab pipeline that fires on every commit and every Merge Request. So are we done? Not quite. Code in production sits there for weeks or months, and during that time researchers keep finding new CVEs in the dependencies you are already shipping. In Part 11 of the GitLab DevSecOps series, Patrick Steger and I add a scheduled pipeline so the production branch gets re-scanned automatically — without anyone having to push a commit.
In the previous nine sessions Patrick Steger and I built a GitLab DevSecOps pipeline that runs SAST, secret detection, software composition analysis, container scanning and DAST. Useful — but only if it actually catches issues before they reach the default branch. In Part 10 we close that loop: we wire the pipeline into Merge Requests so every change is scanned, the deltas against the default branch are visible, and approvals are required when new high or critical vulnerabilities appear.
In this conference talk, I discuss one of the most fundamental topics in DevOps: thinking in systems and value streams. When I work with companies on their DevOps transformations, I consistently see the same patterns. The business has bright ideas. They write them into Word documents and Jira tickets. They throw them over a wall of confusion to development. Development builds something and throws it to testing. Testing compares what was specified with what was built (never quite the same), tests something, and throws it to operations. Operations asks “How can we operate that?” and somehow, with great effort, they get it running. Then the customer sees it and says: “What is that? That is not what we ordered.”
After eight sessions of adding scanners to our GitLab pipeline — SAST, secret detection, SCA, license compliance, container scanning, DAST — we now have a different problem. We have hundreds of vulnerability findings. In Part 9, Patrick Steger and I look at GitLab’s built-in Vulnerability Management: what it gives you, where it falls short, and how to actually triage findings without losing your mind.
Everything we have done in the GitLab DevSecOps pipeline so far has been static — analysis of source code, dependencies, containers and configuration. In Part 8, Patrick Steger and I cross the line into Continuous Delivery and add Dynamic Application Security Testing. DAST means we deploy the application, start it, and then attack it from the outside with an automated penetration testing tool. GitLab ships this capability out of the box, powered by OWASP ZAP.
Hard-coded passwords and API keys are still one of the most common ways credentials leak. They get committed by accident, stay in the git history forever, and only show up when someone is already exploiting them. In Part 7 of our GitLab DevSecOps series, Patrick Steger and I add Secret Detection to the same pipeline we have been growing — one line of YAML — and then look at what GitLeaks actually finds, what it quietly misses, and what to do about it.
We have already wired SAST, secret detection, and software composition analysis into the GitLab pipeline. Those checks cover the source code and its dependencies — but the artifact we actually ship is a container image. Operating system packages, the base image, and everything copied in along the way can carry vulnerabilities of their own. In Part 6 of our series, Patrick Steger and I add container scanning to the pipeline, build a Docker image from the jar we compiled earlier, and push it through Trivy and Grype.
Software composition analysis takes care of the libraries you pull in. But what about the code your own team writes? That is where Static Application Security Testing comes in. In Part 5 of our GitLab DevSecOps series, Patrick Steger and I add SAST to the pipeline, plant a few realistic vulnerabilities in our Spring Boot sample, and watch GitLab pick them up.
You ship a Java application that depends on Spring Boot, which depends on dozens of other libraries, each with its own license — and most teams cannot tell you what those licenses actually are. In Part 4 of our GitLab DevSecOps series, Patrick Steger and I add license compliance to the pipeline so the question is answered automatically on every commit. The good news: with GitLab Ultimate, this is one template line away.
Your code is the small part. The libraries you pull in are the big part — and that is where most of your CVEs live. In Part 3 of the GitLab DevSecOps series, Patrick Steger and I bring up a tiny Spring Boot demo, wire it into a GitLab pipeline, and then add Software Composition Analysis with a single include line.
Before we can shift any security checks left, we need a project, a repository, and a pipeline that actually builds something. In Part 2 of our GitLab DevSecOps series, Patrick Steger and I log into GitLab, create a new .NET Core project from a template, and look at the .gitlab-ci.yml file that GitLab generates for us — including the build and test jobs that will become the foundation for everything we add later.
Why does security still get bolted on at the end of the development process, and how do we move it earlier without slowing teams down? In Part 1 of our GitLab DevSecOps series, Patrick Steger and I set the stage: what GitLab is, what shifting security left really means, and which CI/CD concepts you have to understand before you can build a DevSecOps pipeline that actually works.