From Scanners to an Action Plan: An AppSec Pipeline for DORA
Several thousand findings. That is what came back the first time we pointed security scanners at a repository that had been running in production for a while. The team opened the list, scrolled, and closed it. A month later, almost nothing had been fixed.
Nobody was lazy. The findings simply had nowhere to go. There was no place where a finding became a task with an owner and a deadline, so the list stayed a list.
If you build software for banks, insurers or payment providers, you have probably lived through the same thing. And now you have a second problem on top of it. DORA (the Digital Operational Resilience Act, Regulation (EU) 2022/2554) expects you to test your applications continuously and to track what you do about what you find. It tells you what, it doesn’t tell you how.
What DORA actually requires from application security
Strip away the legal language and DORA's technical expectations for application security, it comes down to five practices:
- Static application security testing (SAST): analysing your source code for vulnerabilities before it ships.
- Dynamic application security testing (DAST): probing the running application the way an attacker would.
- Analysis of components: knowing which open source libraries and base images you depend on, and which of them are vulnerable. The industry calls this SCA (Software Composition Analysis).
- Continuous vulnerability management: a state that refreshes itself, not an annual test.
- An action plan, with implementation tracked: every accepted finding gets an owner, a deadline and a visible status.
The fifth point is the one most teams skip. It is also the one that separates a scan from a process, and it is the one an auditor will ask about first. NIS2 (the second Network and Information Security Directive) and the CRA (Cyber Resilience Act) push in exactly the same direction, so whatever you build for DORA will serve you three times over.
The pipeline architecture: two flows and one brain
Two flows feed one central place, and that central place talks to the tracker your engineers already use.
| Flow | Trigger | What runs | Where results go |
| Build time | Every push or merge request | SAST, SCA, DAST | Central place, through the reimport API. Can fail the pipeline and block the merge. |
| After release | Nightly schedule, no code change | SCA tool re-scan of the released source and images, same SBOM | The same product in the central place. Never blocks anything. |
| Remediation | A finding is verified in triage | Two-way Jira sync | A Jira ticket in the engineering team's own backlog. Status flows back to the central place. |
The build time is fast and is allowed to block. A push or a merge request triggers CI, the scanners run inside it, and every result goes to the central vulnerability management platform through its reimport API. That is one call per scanner in the pipeline, nothing more. If you work with merge requests, fail the pipeline on new vulnerabilities and block the merge.
The after release is continuous and never blocks. A schedule re-scans the sources and images you have already published, without a single change in the code, and those results land in the same place.
Jira solves the most common objection you will hear, that engineers do not want yet another tool. A finding you accept becomes a ticket where they already work. When the ticket closes, the status flows back. If the next scan detects the same vulnerability because it was never removed, the ticket reopens on its own.
Detection is the easy part: SAST, SCA and DAST
SAST covers static analysis. The only setting that decides anything is the quality gate, because the quality gate is what says whether the build passed.
SCA covers open source components. One binary, and it scans both the filesystem and the container image. It also produces the SBOM (Software Bill of Materials), the inventory of every component in your artefact. Remember the SBOM. We reuse it after deployment, and that reuse is the whole point of the next section.
DAST covers dynamic testing. It needs a running application and a working login, and that is where most pipelines give up. We handle authentication machine-to-machine, so the DAST tool gets past the login page without a human typing a password. Add DAST tool when you can run the application with working auth in CI. Until then, do not let it hold up the rest.
Continuous SBOM monitoring: the part that separates a pipeline from a tool list
A scan in the build answers one question: was this artefact vulnerable at the moment we built it? It says nothing about tomorrow. And vulnerabilities are not disclosed according to your release schedule.
So we run the same SCA tool configuration on a schedule, over the sources and images already in production, and send the results back through the same reimport call. A CVE (Common Vulnerabilities and Exposures entry) disclosed today shows up tonight, on the exact component and version that is already serving customers.
Two design decisions made this work in practice:
- The scheduled scans live in a separate GitLab project. Product teams do not have to implement or maintain periodic scanning, and they cannot opt out of it either.
- Deduplication keeps one finding with its history, not one row per run. The same component across hundreds of scans stays a single finding. A newly disclosed vulnerability appears as a genuinely new item, which is exactly what makes it visible instead of noise.
This is what DORA means by continuous management of open source vulnerabilities: not an annual test, but a state that refreshes itself, per software version.
Each vulnerability carries a severity, and the SLA (Service Level Agreement) for remediation differs by severity. Depending on the product, the project, or the contract, you may need to track different SLAs side by side.
Where a finding becomes a task
This is where scanning stops being a tool and becomes a process.
Four scanners, three report formats, one queue. Reimport attaches every new scan to the same product, so you do not get a new pile of findings each build. You get a new version of the same list.
Deduplication was the hardest part of the whole setup, and we tuned the rules for weeks. How you deduplicate depends on how you work and how you version the complete product. We deduplicate per version, not across the whole product, because we need to know when one vulnerability lives in several supported versions. The remediation has to be planned and carried out on each of them.
Triage is simple: severity, owner, due date, SLA clock. Every open finding has a name next to it. That single rule did more for remediation than any scanner setting.
Jira sync closes the loop. An accepted finding becomes a ticket in the engineering team's own backlog, assigned either immediately or into an upcoming sprint depending on the SLA for that severity. The status flows back. And out of the same data comes the report we hand to a client or an auditor.
DORA calls this adopting an action plan and monitoring its implementation.
Pain and lessons: what the documentation does not tell you
Tune the rules before you tune the people.
The first real scan buried us in false positives. Once a team loses trust in the list, you have lost it for good, and no amount of process brings it back. Spend the first weeks on rule tuning, not on chasing engineers.
Deduplication across tools was the real engineering work
The same vulnerability from two tools looks like two findings, and across a hundred builds like a hundred findings. The Jira integration was the second biggest job. Budget for both. The scanners themselves are a minor part of the equation.
Alert only on what someone will act on
At the start we sent every notification to a chat channel. After a week nobody read it. Today a notification goes out for two things only: a new critical finding on a component in production, and a vulnerability approaching its SLA deadline. And the recipients are not the engineers. They are the people responsible for planning and executing the action plan.
Fail the build on new vulnerabilities in changed code, never on the backlog
This is the question everyone asks. If you fail the build on the whole historical backlog, someone will disable the job within a week and you will be left without a pipeline at all.
Where to start
You do not need all of this on day one. In our experience, the order that works is:
- This week: turn on SAST with a quality gate and SCA in the build. Send both to your central vulnerability management platform through the reimport API. One call per scanner.
- This month: add the nightly SCA re-scan of released images from a separate project, tune deduplication per version, and give every open finding an owner and a due date.
- This quarter: connect Jira in both directions, set SLAs by severity, and generate the first report you would be comfortable handing to an auditor. Add the DAST tool once you can run the application with working auth in CI.
Detection takes a week. Remediation as a process takes a quarter. DORA cares about the second one, and so, honestly, should you.
ASEE Cybersecurity Awareness Month
This article is part of our Cybersecurity Awareness Month series.
Find the full series on our Blog.
Stay informed. Stay secure.